diff --git a/doc/pius.1 b/doc/pius.1 index 84adc3a..85db04a 100644 --- a/doc/pius.1 +++ b/doc/pius.1 @@ -47,6 +47,8 @@ Hostname of SMTP server. [default: \fIlocalhost\fP] Use the pexpect module for signing and drop to the gpg shell for entering the passphrase. [default: false] .IP "\fB\-I\fP, \fB\-\-import\fP" Also import the unsigned keys from the keyring into the default keyring. Ignored if \fB\-r\fP is not specified, or if it's the same as the default keyring. +.IP "\fB\-L\fP, \fB\-\-save\-to\-mail\-dir\fP" +Instead of calling SMTP, save the email to this directory. Useful for signing from an air gapped machine. The saved email files can be sent using your own MTA such as sendmail or mailx. .IP "\fB\-m\fP \fIFROM\-EMAIL\fP, \fB\-\-mail=\fP\fIFROM\-EMAIL\fP" Email the encrypted, signed keys to the respective email addresses using \fIFROM\-EMAIL\fP as the sender. See also \fB\-H\fP and \fB\-P\fP. .IP "\fB\-M\fP \fIFILE\fP, \fB\-\-mail\-text=\fP\fIFILE\fP" diff --git a/libpius/mailer.py b/libpius/mailer.py index 55231aa..c52e6c0 100644 --- a/libpius/mailer.py +++ b/libpius/mailer.py @@ -21,7 +21,7 @@ class PiusMailer(object): def __init__(self, mail, display_name, host, port, user, tls, no_mime, - override, msg_text, tmp_dir): + override, msg_text, tmp_dir, local_mail_dir): self.mail = mail self.display_name = display_name self.host = host @@ -33,6 +33,7 @@ def __init__(self, mail, display_name, host, port, user, tls, no_mime, self.address_override = override self.message_text = msg_text self.tmp_dir = tmp_dir + self.local_mail_dir = local_mail_dir @staticmethod def add_options(parser): @@ -258,40 +259,51 @@ def _send_mail(self, to, msg): msg['From'] = self.mail if self.address_override: msg['To'] = self.address_override + env_to = [msg['To']] else: msg['To'] = to + env_to = [msg['To'], self.mail] msg['Date'] = formatdate(localtime=True) - try: - smtp = smtplib.SMTP(self.host, self.port) - if self.tls: - # NOTE WELL: SECURITY IMPORTANT NOTE! - # In python 2.6 if you attempt to starttls() and the server doesn't - # understand an exception is raised. However before that, it just - # carried on and one could attempt to auth over a plain-text session. - # This is BAD! - # - # So, in order be secure on older pythons we ehlo() and then check the - # response before attempting startls. - smtp.ehlo() - if not smtp.has_extn('STARTTLS'): - # Emulate 2.6 behavior - raise smtplib.SMTPException('Server does not support STARTTLS') - smtp.starttls() - # must re-ehlo after STARTTLS - smtp.ehlo() - # Don't want to send auth information unless we're TLS'd - if self.user: - smtp.login(self.user, self.password) - if self.address_override: - env_to = self.address_override - else: - # BCC the user... - env_to = [msg['To'], self.mail] - - smtp.sendmail(self.mail, env_to, msg.as_string()) - smtp.quit() - except smtplib.SMTPException as emsg: - raise MailSendError(emsg) - except socket.error as emsg: - raise MailSendError(emsg) + if self.local_mail_dir: + if not os.path.isdir(self.local_mail_dir): + os.mkdir(self.local_mail_dir) + if not self.address_override: + msg['Bcc'] = self.mail + email = open(os.path.join(self.local_mail_dir, msg['To']), 'w') + email.write(str(msg)) + email.close() + else: + try: + smtp = smtplib.SMTP(self.host, self.port) + if self.tls: + # NOTE WELL: SECURITY IMPORTANT NOTE! + # In python 2.6 if you attempt to starttls() and the server doesn't + # understand an exception is raised. However before that, it just + # carried on # and one could attempt to auth over a plain-text session. + # This is BAD! + # + # So, in order be secure on older pythons we ehlo() and then check the + # response before attempting startls. + smtp.ehlo() + if not smtp.has_extn('STARTTLS'): + # Emulate 2.6 behavior + raise smtplib.SMTPException('Server does not support STARTTLS') + smtp.starttls() + # must re-ehlo after STARTTLS + smtp.ehlo() + # Don't want to send auth information unless we're TLS'd + if self.user: + smtp.login(self.user, self.password) + if self.address_override: + env_to = self.address_override + else: + # BCC the user... + env_to = [msg['To'], self.mail] + + smtp.sendmail(self.mail, env_to, msg.as_string()) + smtp.quit() + except smtplib.SMTPException as emsg: + raise MailSendError(emsg) + except socket.error as emsg: + raise MailSendError(emsg) diff --git a/pius b/pius index 2363e82..8f6bf0f 100755 --- a/pius +++ b/pius @@ -158,6 +158,10 @@ def main(): ' into the default keyring. Ignored if -r is not' ' specified, or if it\'s the same as the default' ' keyring.') + parser.add_option('-L', '--save-to-mail-dir', dest='local_mail_dir', + metavar='DIRECTORY', + help='Instead of calling SMTP, save' + ' the email to this directory.') parser.add_option('-m', '--mail', dest='mail', metavar='EMAIL', nargs=1, type='email', help='Email the encrypted, signed keys to the' @@ -243,7 +247,8 @@ def main(): options.mail_no_pgp_mime, options.mail_override, options.mail_text, - options.tmp_dir + options.tmp_dir, + options.local_mail_dir ) else: mailer = None