Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to save generated emails #92

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/pius.1
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
80 changes: 46 additions & 34 deletions libpius/mailer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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):
Expand Down Expand Up @@ -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')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with open(os.path.join(self.local_mail_dir, msg['To']), 'w') as email:
  email.write(str(msg))

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:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is no longer needed, you do it above.

env_to = self.address_override
else:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

# 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)
7 changes: 6 additions & 1 deletion pius
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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
Expand Down