pgp: force protocol/micalg ordering in doctest output.
[pgp-mime.git] / pgp_mime / smtp.py
1 # Copyright (C) 2012 W. Trevor King <wking@tremily.us>
2 #
3 # This file is part of pgp-mime.
4 #
5 # pgp-mime is free software: you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation, either version 3 of the License, or (at your option) any later
8 # version.
9 #
10 # pgp-mime is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License along with
15 # pgp-mime.  If not, see <http://www.gnu.org/licenses/>.
16
17 import configparser as _configparser
18 import smtplib as _smtplib
19
20 from . import LOG as _LOG
21
22
23 SENDMAIL = ['/usr/sbin/sendmail', '-t']
24
25
26 def get_smtp_params(config):
27     r"""Retrieve SMTP paramters from a config file.
28
29     >>> from configparser import ConfigParser
30     >>> config = ConfigParser()
31     >>> config.read_string('\n'.join([
32     ...             '[smtp]',
33     ...             'host: smtp.mail.uu.edu',
34     ...             'port: 587',
35     ...             'starttls: yes',
36     ...             'username: rincewind',
37     ...             'password: 7ugg@g3',
38     ...             ]))
39     >>> get_smtp_params(config)
40     ('smtp.mail.uu.edu', 587, True, 'rincewind', '7ugg@g3')
41     >>> config = ConfigParser()
42     >>> get_smtp_params(ConfigParser())
43     (None, None, None, None, None)
44     """
45     try:
46         host = config.get('smtp', 'host')
47     except _configparser.NoSectionError:
48         return (None, None, None, None, None)
49     except _configparser.NoOptionError:
50         host = None
51     try:
52         port = config.getint('smtp', 'port')
53     except _configparser.NoOptionError:
54         port = None
55     try:
56         starttls = config.getboolean('smtp', 'starttls')
57     except _configparser.NoOptionError:
58         starttls = None
59     try:
60         username = config.get('smtp', 'username')
61     except _configparser.NoOptionError:
62         username = None
63     try:
64         password = config.get('smtp', 'password')
65     except _configparser.NoOptionError:
66         password = None
67     return (host, port, starttls, username, password)
68
69 def get_smtp(host=None, port=None, starttls=None, username=None,
70              password=None):
71     """Connect to an SMTP host using the given parameters.
72
73     >>> import smtplib
74     >>> try:  # doctest: +SKIP
75     ...     smtp = get_smtp(host='smtp.gmail.com', port=587, starttls=True,
76     ...         username='rincewind@uu.edu', password='7ugg@g3')
77     ... except smtplib.SMTPAuthenticationError as error:
78     ...     print('that was not a real account')
79     that was not a real account
80     >>> smtp = get_smtp()  # doctest: +SKIP
81     >>> smtp.quit()  # doctest: +SKIP
82     """
83     if host is None:
84         host = 'localhost'
85     if port is None:
86         port = _smtplib.SMTP_PORT
87     if username and not starttls:
88         raise ValueError(
89             'sending passwords in the clear is unsafe!  Use STARTTLS.')
90     _LOG.info('connect to SMTP server at {}:{}'.format(host, port))
91     smtp = _smtplib.SMTP(host=host, port=port)
92     smtp.ehlo()
93     if starttls:
94         smtp.starttls()
95     if username:
96         smtp.login(username, password)
97     #smtp.set_debuglevel(1)
98     return smtp
99
100 def mail(message, smtp=None, sendmail=None):
101     """Send an email ``Message`` instance on its merry way.
102
103     We can shell out to the user specified sendmail in case
104     the local host doesn't have an SMTP server set up
105     for easy ``smtplib`` usage.
106
107     >>> from pgp_mime.email import encodedMIMEText
108     >>> message = encodedMIMEText('howdy!')
109     >>> message['From'] = 'John Doe <jdoe@a.gov.ru>'
110     >>> message['To'] = 'Jack <jack@hill.org>, Jill <jill@hill.org>'
111     >>> mail(message=message, sendmail=SENDMAIL)  # doctest: +SKIP
112     """
113     _LOG.info('send message {} -> {}'.format(message['from'], message['to']))
114     if smtp:
115         smtp.send_message(msg=message)
116     elif sendmail:
117         execute(
118             sendmail, stdin=message.as_string().encode('us-ascii'),
119             close_fds=True)
120     else:
121         smtp = _smtplib.SMTP()
122         smtp.connect()
123         smtp.send_message(msg=message)
124         smtp.close()