class Identity(object): """An identity suitable for sending email from. This contains both the user's full name, email address and SMTP information.""" __log = logging.getLogger(__name__ + '.Identity') def __init__(self, name, email_, use_ssl = False, use_tls = False, username = None, password = None, **kwargs): """Initialise an identity. The remain keyword arguments hold the SMTP server connection information. All fields are optional and are in effect passed to smtplib. The fields are: - host: The hostname of the SMTP server. - port: The port used to connect to the server. - username: The username to authenticate to the SMTP server with. - password: The password to authenticate to the SMTP server with. - use_ssl: Connect via SSL (default: no). - use_tls: Attempt to make use of the STARTTLS command (default: no). If use_ssl is True, try to connect to the SMTP server via SSL. """ self._interface = TerminalInterface() self._name = name self._email = email_ # Defaults self._smtp_vars = { 'host': None, 'port': None } self._use_ssl = use_ssl self._use_tls = use_tls if username is not None: self._credentials = (username, password) else: self._credentials = None # Copy the SMTP vars for key in ['host', 'port']: if key in kwargs: self._smtp_vars[key] = kwargs[key] if self._smtp_vars['host'] is None: raise KeyError('Host not specified') Identity.__log.info('Initialised identity "%s".' % self.get_rfc2822_address()) Identity.__log.info('SMTP server options: %s' % self._smtp_vars) Identity.__log.info('Security options: SSL: %s, TLS: %s' % (self._use_ssl, self._use_tls)) if self._credentials is not None: Identity.__log.info('Security credentials: username: %s, password: %s' % ( self._credentials[0], self._credentials[1] is not None)) def get_email(self): """Return the email address.""" return self._email def get_name(self): """Return the full name.""" return self._name def get_rfc2822_address(self): """Return the RFC 2822 address for this identity (e.g. 'John Smith <*****@*****.**>'). """ return formataddr((self._name, self._email)) def sendmail(self, to, message): """Send mail to one or more recipients. The required arguments are a list of RFC 822 to-address strings (a bare string will be treated as a list with 1 address), and a message string. """ # If we were passed a bare string as the To: address, convert it to # a single element list. if isinstance(to, str): to = [ to, ] # Send one email with the appropriate recipient list. server = self._smtp_server() server.sendmail(self.get_rfc2822_address(), to, message) server.quit() def save_to_config(self, config = Config()): config.set('user', 'name', self._name) config.set('user', 'email', self._email) config.set('smtp', 'host', self._smtp_vars['host']) config.set('smtp', 'port', self._smtp_vars['port']) config.set('smtp', 'use_ssl', self._use_ssl) config.set('smtp', 'use_tls', self._use_tls) if self._credentials is not None: config.set('smtp', 'username', self._credentials[0]) config.set('smtp', 'password', self._credentials[1]) self._interface.new_section() self._interface.message(""" Your default identity has been saved to the configuration. If you want to modify this information at any future time, you can do so with the following command: %s --set identity""" % os.path.basename(sys.argv[0])) def send_test_email(self): message = MIMEText('This is an example email from throw.') message['Subject'] = 'A test email from throw' message['To'] = self.get_rfc2822_address() message['From'] = self.get_rfc2822_address() import socket # for socket.error try: self.sendmail( self.get_rfc2822_address(), message.as_string()) self._interface.message("""The test email was successfully sent. Check your mail to see if you get it.""") return True except smtplib.SMTPException as e: self._interface.error('Failed to send test email: the SMTP server said "%s".' % e) except socket.error as e: self._interface.error('Failed to send test email: "%s".' % e) return False def _smtp_server(self): """Return a smtplib SMTP object correctly initialised and connected to a SMTP server suitable for sending email on behalf of the user.""" if self._use_ssl: server = smtplib.SMTP_SSL(**self._smtp_vars) else: server = smtplib.SMTP(**self._smtp_vars) if self._use_tls: server.starttls() if self._credentials is not None: passwd = self._credentials[1] if passwd is None: passwd = self._interface.input( \ 'Password for %s' % (self._credentials[0],), no_echo=True) server.login(*self._credentials) # if we succeeded, cache the password self._credentials = (self._credentials[0], passwd) return server