Exemplo n.º 1
1
def send_to_admin(serversmtp, frm, to, error, cur):
    logger.info('Send email about error to admin')
    # Get admin email address from database
    cur.execute("SELECT mb_value FROM `mb_properties` WHERE mb_field='Admin email'")
    admin = cur.fetchone()[0]
    # Create email fo admin
    msg = Message()
    msg.add_header('Subject', 'SRK DPIportal [Mail Sender] Impossible send email!')
    msg.add_header('Date', formatdate(localtime=True))
    msg.add_header('X-Mailer', 'MailSender')
    msg.add_header('Message-ID', make_msgid())
    msg.add_header('From', frm)
    msg.add_header('To', admin)
    msg.set_payload('Subject:' + msg['Subject'] + '\n'
                    'From:' + frm + '\n'
                    'To:' + admin + '\n\n'
                    'Impossible send email to ' + to + '\n'
                    'Error:\n' + error)
    try:
        serversmtp.sendmail(msg['From'],
                            msg['To'].split('; '),
                            msg.get_payload())
        logger.info('Mail was send to %s' % admin)
    except Exception as e:
        logger.error(str(e))
    logger.info('Impossible send email to admin %s' % admin)
Exemplo n.º 2
0
    def test_nested_series(self):
        """Handle a series sent in-reply-to an existing series."""
        # create an old series with a "cover letter"
        msgids = [make_msgid()]
        project = create_project()
        series_v1 = create_series(project=project)
        create_series_reference(msgid=msgids[0], series=series_v1)

        # ...and three patches
        for i in range(3):
            msgids.append(make_msgid())
            create_series_reference(msgid=msgids[-1], series=series_v1)

        # now create a new series with "cover letter"
        msgids.append(make_msgid())
        series_v2 = create_series(project=project)
        ref_v2 = create_series_reference(msgid=msgids[-1], series=series_v2)

        # ...and the "first patch" of this new series
        msgid = make_msgid()
        email = self._create_email(msgid, msgids)
        series = find_series(project, email)

        # this should link to the second series - not the first
        self.assertEqual(len(msgids), 4 + 1)  # old series + new cover
        self.assertEqual(series, ref_v2.series)
Exemplo n.º 3
0
 def reassemble_mail(self, parsed_email, to_keep, attachments):
     original_msgid = parsed_email.get_all('Message-ID')
     try:
         parsed_email.replace_header('Message-ID', make_msgid())
     except:
         parsed_email.add_header('Message-ID', make_msgid())
     if to_keep:
         if parsed_email.is_multipart():
             parsed_email.set_payload([to_keep[0]])
         else:
             parsed_email.set_payload(to_keep[0])
             return parsed_email
     else:
         info_msg = MIMEText('Empty Message', _subtype='plain', _charset='utf-8')
         parsed_email.set_payload([info_msg])
     for k in to_keep[1:]:
         parsed_email.attach(k)
     info = 'The attachments of this mail have been sanitzed.\nOriginal Message-ID: {}'.format(original_msgid)
     info_msg = MIMEText(info, _subtype='plain', _charset='utf-8')
     info_msg.add_header('Content-Disposition', 'attachment', filename='Sanitized.txt')
     parsed_email.attach(info_msg)
     for f in attachments:
         msg = self.pack_attachment(f)
         for m in msg:
             parsed_email.attach(m)
     return parsed_email
Exemplo n.º 4
0
    def test_first_reply(self):
        msgid_a = make_msgid()
        msgid_b = make_msgid()
        email = self._create_email(msgid_b, [msgid_a])

        # assume msgid_a was already handled
        ref = create_series_reference(msgid=msgid_a)

        series = find_series(email)
        self.assertEqual(series, ref.series)
def send_mail(from_email, to_emails, subject, body, host='mail', port=25):
    """Send an email via SMTP
    
    @param from_email: email address for From: header
    @type from_email: str
    
    @param to_emails: sequence of email addresses for To: header
    @type to_email: [str]
    
    @param subject: text for Subject: header
    @type subject: unicode
    
    @param body: text for message body
    @type body: unicode
    
    @param host: mail server host
    @type host: str
    
    @param port: mail server port
    @type port: int
    """
    
    connection = smtplib.SMTP(host, port)
    msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
    msg['Subject'] = subject.encode('utf-8')
    msg['From'] = from_email
    msg['To'] = ', '.join(to_emails)
    msg['Date'] = formatdate()
    msg['Message-ID'] = make_msgid()
    connection.sendmail(from_email, to_emails, msg.as_string())
    connection.close()
Exemplo n.º 6
0
def map_message(message, table):

    def container(message_id):
        return table.setdefault(message_id, Container())

    w = Wrapper(message)
    this = container(w.message_id)

    # process case when we have two messages
    # with the same id, we should put
    # our current message to another container
    # otherwise the message would be lost
    if this.message:
        fake_id = make_msgid()
        this = container(fake_id)
    this.message = w

    # link message parents together
    prev = None
    for parent_id in w.references:
        parent = container(parent_id)
        if prev and not parent.parent and not introduces_loop(prev, parent):
            prev.add_child(parent)
        prev = parent

    # process case where this message has parent
    # unlink the old parent in this case
    if this.parent:
        this.parent.remove_child(this)

    # link to the cool parent instead
    if prev and not introduces_loop(prev, this):
        prev.add_child(this)
Exemplo n.º 7
0
 def generate_reply(self, message, result):
     try:
         from_mailaddr = '*****@*****.**'
         if message.get('Reply-To'):
             to = message.get('Reply-To')
             (to_realname,to_mailaddr) = email.utils.parseaddr(to)
         elif message.get('From'):
             to = message.get('From')
             (to_realname,to_mailaddr) = email.utils.parseaddr(to)
         msg = MIMEMultipart('encrypted', protocol='application/pgp-encrypted')
         msg['From'] = from_mailaddr
         msg['To'] = to
         msg['Subject'] = 'ud-mailgate processing results'
         msg['Message-Id'] = make_msgid()
         msg['In-Reply-To'] = message['Message-Id']
         msg['Date'] = formatdate(localtime=True)
         msg['Content-Disposition'] = 'inline'
         part1 = MIMEApplication(_data='Version: 1\n', _subtype='pgp-encrypted', _encoder=encode_7or8bit)
         part1['Content-Disposition'] = 'attachment'
         msg.attach(part1)
         part2 = MIMEApplication(_data=result, _subtype='octet-stream', _encoder=encode_7or8bit)
         part2['Content-Disposition'] = 'inline; filename="msg.asc"'
         msg.attach(part2)
         fd = StringIO.StringIO()
         g = Generator(fd, mangle_from_=False)
         g.flatten(msg)
         if self.options['console']:
             self.stdout.write(fd.getvalue() + '\n')
         else:
             s = smtplib.SMTP('localhost')
             s.sendmail(from_mailaddr, to_mailaddr, fd.getvalue())
             s.quit()
     except Exception as err:
         raise CommandError(err)
Exemplo n.º 8
0
    def __init__(self, subject=None,
                 recipients=None,
                 body=None,
                 html=None,
                 sender=None,
                 cc=None,
                 bcc=None,
                 attachments=None,
                 reply_to=None,
                 date=None,
                 charset=None,
                 extra_headers=None,
                 mail_options=None,
                 rcpt_options=None):

        sender = sender

        if isinstance(sender, tuple):
            sender = formataddr(sender)

        self.recipients = recipients or []
        self.subject = subject
        self.sender = sender or current_app.extensions['mail'].default_sender
        self.reply_to = reply_to
        self.cc = cc or []
        self.bcc = bcc or []
        self.body = body
        self.html = html
        self.date = date
        self.msgId = make_msgid()
        self.charset = charset
        self.extra_headers = extra_headers
        self.mail_options = mail_options or []
        self.rcpt_options = rcpt_options or []
        self.attachments = attachments or []
Exemplo n.º 9
0
 def setUp(self):
     mail = 'Message-Id: %s\n' % make_msgid() + \
            'From: %s\n' % self.sender + \
            'Subject: %s\n\n' % self.subject_header + \
            'test\n\n' + defaults.patch
     self.projects = defaults.project
     self.email = message_from_string(mail)
Exemplo n.º 10
0
def doSendmail(server, subject, mailtext):
	"""
	This local function send the eMail

	@type  server:   SMTP
	@param server:   An SMTP-Object that represents an open connection to an eMail-Server
	@type  subject:  string
	@param subject:  Subject for the eMail
	@type  mailtext: string
	@param mailtext: Mailtext for the eMail

	@return:    nothing
	@exception: Exception if smtp.sendmail failed
	"""
	try:
		msg = MIMEText(mailtext, 'plain', 'UTF-8')
		msg['From'] = globalVars.config.get("eMail", "from")
		msg['To']   = globalVars.config.get("eMail", "to")
		msg['Subject'] = subject
		msg['Date'] = formatdate()
		msg['Message-Id'] = make_msgid()
		msg['Priority'] = globalVars.config.get("eMail", "priority")
		server.sendmail(globalVars.config.get("eMail", "from"), globalVars.config.get("eMail", "to").split(), msg.as_string())
	except:
		logging.error("send eMail failed")
		logging.debug("send eMail failed", exc_info=True)
		raise
Exemplo n.º 11
0
 def flush(self,Nmin):
     res=[]
     with locker.lock('accumulating_notifcations'):
         for key in self.cache.keys():
             (subject,sender,addressee)=key
             if self.cache[key]['N'] <= Nmin: 
                 ## flush only above a certain amount of messages
                 continue
             destination = addressee.split(COMMASPACE)
             text = self.cache[key]['Text']
             msg = MIMEMultipart()
             
             msg['From'] = sender
             msg['To'] = addressee
             msg['Date'] = formatdate(localtime=True)
             new_msg_ID = make_msgid()  
             msg['Message-ID'] = new_msg_ID 
             msg['Subject'] = subject
             
             ## add a signature automatically
             text += '\n\n'
             text += 'McM Announcing service'
             #self.logger.log('Sending a message from cache \n%s'% (text))
             try:
                 msg.attach(MIMEText(text))
                 smtpObj = smtplib.SMTP()
                 smtpObj.connect()
                 smtpObj.sendmail(sender, destination, msg.as_string())
                 smtpObj.quit()
                 self.cache.pop(key)
                 res.append( subject )
             except Exception as e:
                 print "Error: unable to send email", e.__class__
         return res
Exemplo n.º 12
0
def create_patch(**kwargs):
    """Create 'Patch' object."""
    num = Patch.objects.count()

    # NOTE(stephenfin): Even though we could simply pass 'series' into the
    # constructor, we don't as that's not what we do in the parser and not what
    # our signal handlers (for events) expect
    series = kwargs.pop('series', None)
    number = kwargs.pop('number', None)

    values = {
        'submitter': create_person() if 'submitter' not in kwargs else None,
        'delegate': None,
        'project': create_project() if 'project' not in kwargs else None,
        'msgid': make_msgid(),
        'state': create_state() if 'state' not in kwargs else None,
        'name': 'testpatch%d' % num,
        'headers': '',
        'content': 'Patch testpatch%d' % num,
        'diff': SAMPLE_DIFF,
    }
    values.update(kwargs)

    if 'patch_project' not in values:
        values['patch_project'] = values['project']

    patch = Patch.objects.create(**values)

    if series:
        number = number or series.patches.count() + 1
        series.add_patch(patch, number)

    return patch
Exemplo n.º 13
0
def sendmail(to, subj, body, html=None, sender=None, cc=None, bcc=None, config={}):
    sendto = to

    msg = MIMEMultipart('alternative')

    msg.attach(MIMEText(body, 'plain'))
    if html:
        msg.attach(MIMEText(html, 'html'))

    msg['To'] = ','.join(to)
    msg['From'] = sender or config.get('from', '')
    msg['Subject'] = subj
    msg['Message-ID'] = make_msgid()
    msg['Date'] = formatdate()

    if cc is not None:
        msg['cc'] = ','.join(cc)
        sendto += cc
    if bcc is not None:
        msg['bcc'] = ','.join(bcc)
        sendto += bcc

    if config.get('ssl'):
        smtp_cls = SMTP_SSL
    else:
        smtp_cls = SMTP
    smtp = smtp_cls(host=config['host'], port=config['port'])
    smtp.ehlo()
    if config.get('tls'):
        smtp.starttls()
    smtp.login(user=config['username'], password=config['password'])
    smtp.sendmail(sender or config.get('from') or config.get('username'), sendto, msg.as_string())
    smtp.close()
    yield
Exemplo n.º 14
0
 def send_message(self,message,subject=None):
     
     helo=self.configvars['helo']
     if helo=='${myhostname}':
         helo=socket.gethostname()
     
     smtp=smtplib.SMTP(self.configvars['host'], int(self.configvars['port']), helo,20)
     
     if self.configvars['starttls'].lower().strip()=='yes':
         smtp.starttls()
     
     user=self.configvars['username'].strip()
     pw=self.configvars['password'].strip()
     if user!='' and pw!='':
         smtp.login(user,pw)
     
     c = message.encode(u'utf8', u'replace')
     txtattach = MIMEText(c, u'plain', u'utf8')
     
     outer = MIMEMultipart(u'alternative')
     outer[u'Subject'] = Header(subject).encode()
     outer[u'To'] = self.recipient
     outer[u'From'] = self.configvars['sender']
     outer[u'auto-submitted'] = 'auto-generated'
     outer[u'Date'] = utils.formatdate(localtime=True)
     outer[u'Message-ID'] = utils.make_msgid()
     outer.attach(txtattach)
     
     smtp.sendmail(self.configvars['sender'], self.recipient, outer.as_string())
Exemplo n.º 15
0
def createEmailTo(sender_name, sender_email, recipient_name, recipient_email,
                  subject, body, format="plain"):
    """Create an :obj:`email.MIMEText.MIMEtext` instance for an email. This
    method will take care of adding addings a date header and message ID
    to the email, as well as quoting of non-ASCII content.
    """
    if isinstance(body, unicode):
        mail=MIMEText(body.encode("utf-8"), format, "utf-8")
    else:
        mail=MIMEText(body, format)

    if sender_name:
        mail["From"]=emailutils.formataddr((sender_name, sender_email))
    else:
        mail["From"]=sender_email
    if recipient_name:
        mail["To"]=emailutils.formataddr((recipient_name, recipient_email))
    else:
        mail["To"]=recipient_email
    mail["Subject"]=Header(subject.encode("utf-8"), "utf-8")
    mail["Message-Id"]=emailutils.make_msgid()
    mail["Date"]=emailutils.formatdate(localtime=True)
    mail.set_param("charset", "utf-8")

    return mail
Exemplo n.º 16
0
    def __init__(self, sender, subject,
                 recipients=None,
                 body=None,
                 html=None,
                 cc=None,
                 bcc=None,
                 attachments=None,
                 reply_to=None,
                 date=None,
                 charset=None,
                 extra_headers=None):

        self.subject = subject
        self.sender = sender
        self.body = body
        self.html = html
        self.date = date
        self.msgId = make_msgid()
        self.charset = charset
        self.extra_headers = extra_headers

        self.cc = cc
        self.bcc = bcc
        self.reply_to = reply_to

        if recipients is None:
            recipients = []

        self.recipients = list(recipients)

        if attachments is None:
            attachments = []

        self.attachments = attachments
Exemplo n.º 17
0
    def get_root_message(self):
        """
        Return the top level Message object which can be a standard Mime message or a
        Multi Part email. All the initial fields are set on the message.
        :return: email.Message object
        """
        if (self.text and self.html) or self.attachments or self.embedded:
            self.message = MIMEMultipart('alternative', None)
            if self.text:
                self.message.attach(self.get_email_part(self.text, 'plain'))
            if self.html:
                self.message.attach(self.get_email_part(self.html, 'html'))
        elif self.text or self.html:
            if self.text:
                self.message = MIMEText(self.text.encode(self.charset), 'plain', self.charset)
            else:
                self.message = MIMEText(self.html.encode(self.charset), 'html', self.charset)
        else:
            self.message = MIMEText('', 'plain', 'us-ascii')
        self.message['From'] = self.format_email_address(email_type='from', emails=[self.sender])
        if self.recipients:
            self.message['To'] = self.format_email_address(email_type='to', emails=self.recipients)

        if self.cc:
            self.message['Cc'] = self.format_email_address(email_type='cc', emails=self.recipients)

        self.message['Subject'] = self.get_header('subject', self.subject)
        self.message['Date'] = formatdate(localtime=True)  # TODO check formatdate
        self.message['Message-ID'] = make_msgid(str(uuid.uuid4()))
        self.message['X-Mailer'] = 'Strudelpy Python Client'
        return self.message
Exemplo n.º 18
0
    def __init__(
        self,
        subject="",
        sender=None,
        to=None,
        cc=None,
        bcc=None,
        body=None,
        html=None,
        date=None,
        charset="utf-8",
        attachments=None,
        extra_headers=None,
    ):

        self.subject = subject
        self.sender = sender
        self.to = to or []
        self.cc = cc or []
        self.bcc = bcc or []
        self.body = body
        self.html = html
        self.date = date
        self.messageID = make_msgid()
        self.charset = charset
        self.attachments = attachments or []
        self.extra_headers = extra_headers or {}
Exemplo n.º 19
0
def send_email(msg_to, msg_subject, msg_body, msg_from=None,
        smtp_server='localhost', envelope_from=None,
        headers={}):

  if not msg_from:
    msg_from = app.config['EMAIL_FROM']

  if not envelope_from:
    envelope_from = parseaddr(msg_from)[1]

  msg = MIMEText(msg_body)

  msg['Subject'] = Header(msg_subject)
  msg['From'] = msg_from
  msg['To'] = msg_to
  msg['Date'] = formatdate()
  msg['Message-ID'] = make_msgid()
  msg['Errors-To'] = envelope_from

  if request:
    msg['X-Submission-IP'] = request.remote_addr

  s = smtplib.SMTP(smtp_server)
  s.sendmail(envelope_from, msg_to, msg.as_string())
  s.close()
Exemplo n.º 20
0
 def __init__(
     self, ext, subject='', recipients=None, body=None, html=None,
     alts=None, sender=None, cc=None, bcc=None, attachments=None,
     reply_to=None, date=None, charset='utf-8', extra_headers=None,
     mail_options=None, rcpt_options=None
 ):
     sender = sender or ext.config.sender
     if isinstance(sender, tuple):
         sender = "%s <%s>" % sender
     self.ext = ext
     self.recipients = recipients or []
     self.subject = subject
     self.sender = sender
     self.reply_to = reply_to
     self.cc = cc or []
     self.bcc = bcc or []
     self.body = body
     self.alts = dict(alts or {})
     self.html = html
     self.date = date
     self.msgId = make_msgid()
     self.charset = charset
     self.extra_headers = extra_headers
     self.mail_options = mail_options or []
     self.rcpt_options = rcpt_options or []
     self.attachments = attachments or []
     for attr in ['recipients', 'cc', 'bcc']:
         if not isinstance(getattr(self, attr), list):
             setattr(self, attr, [getattr(self, attr)])
Exemplo n.º 21
0
def _create_email(msg, msgid=None, sender=None, listid=None):
    msg['Message-Id'] = msgid or make_msgid()
    msg['Subject'] = 'Test subject'
    msg['From'] = sender or 'Test Author <*****@*****.**>'
    msg['List-Id'] = listid or 'test.example.com'

    return msg
Exemplo n.º 22
0
    def send(self,message,rcpt=None):
        """
            message         : email.Message instance
            rcpt            : List of recipients (normally parsed from
                              To/Cc/Bcc fields)
            Send message
        """
        # Check if connected and connect if false
        if not self.is_connected():
            self.connect()
        # Extract recipients
        if rcpt is None:
            rcpt = [ addr[1] for addr in getaddresses((message.get_all('To') or []) + 
                                                      (message.get_all('Cc') or []) + 
                                                      (message.get_all('Bcc') or [])) ]
        # Fill in message fileds if not already set
        # NOTE: this modifies the original message and in particular deletes the Bcc field
        if message['From'] is None:
            message['From'] = self.sender
        if message['Reply-To'] is None:
            message['Reply-To'] = self.sender
        if message['Date'] is None:
            message['Date'] = formatdate(time.time(),localtime=True)
        if message['Message-ID'] is None:
            message['Message-ID'] = make_msgid()
        del message['Bcc']

        # Send message
        self.session.sendmail(self.sender,rcpt,message.as_string())
Exemplo n.º 23
0
        def test_fetch(self):
            # Generate a fresh message-id each time because Gmail is
            # clever and will treat appends of messages with
            # previously seen message-ids as the same message. This
            # breaks our tests when the test message is updated.
            msg_id_header = make_msgid()
            msg = ('Message-ID: %s\r\n' % msg_id_header) + MULTIPART_MESSAGE

            self.client.select_folder(self.base_folder)
            self.client.append(self.base_folder, msg)

            fields = ['RFC822', 'FLAGS', 'INTERNALDATE', 'ENVELOPE']
            msg_id = self.client.search()[0]
            resp = self.client.fetch(msg_id, fields)

            self.assertEqual(len(resp), 1)
            msginfo = resp[msg_id]

            self.assertSetEqual(set(msginfo.keys()), set(fields + ['SEQ']))
            self.assertEqual(msginfo['SEQ'], 1)
            self.assertMultiLineEqual(msginfo['RFC822'], msg)
            self.assertIsInstance(msginfo['INTERNALDATE'], datetime)
            self.assertIsInstance(msginfo['FLAGS'], tuple)
            self.assertTupleEqual(msginfo['ENVELOPE'],
                                  ('Tue, 16 Mar 2010 16:45:32 +0000',
                                   'A multipart message',
                                   (('Bob Smith', None, 'bob', 'smith.com'),),
                                   (('Bob Smith', None, 'bob', 'smith.com'),),
                                   (('Bob Smith', None, 'bob', 'smith.com'),),
                                   (('Some One', None, 'some', 'one.com'), (None, None, 'foo', 'foo.com')),
                                   None, None, None, msg_id_header))
Exemplo n.º 24
0
    def message(self):
        encoding = self.encoding or settings.DEFAULT_CHARSET
        msg = SafeMIMEText(self.body, self.content_subtype, encoding)
        msg = self._create_message(msg)
        msg['Subject'] = self.subject
        msg['From'] = self.extra_headers.get('From', self.from_email)
        self._set_list_header_if_not_empty(msg, 'To', self.to)
        self._set_list_header_if_not_empty(msg, 'Cc', self.cc)
        self._set_list_header_if_not_empty(msg, 'Reply-To', self.reply_to)

        # Email header names are case-insensitive (RFC 2045), so we have to
        # accommodate that when doing comparisons.
        header_names = [key.lower() for key in self.extra_headers]
        if 'date' not in header_names:
            # formatdate() uses stdlib methods to format the date, which use
            # the stdlib/OS concept of a timezone, however, Django sets the
            # TZ environment variable based on the TIME_ZONE setting which
            # will get picked up by formatdate().
            msg['Date'] = formatdate(localtime=settings.EMAIL_USE_LOCALTIME)
        if 'message-id' not in header_names:
            # Use cached DNS_NAME for performance
            msg['Message-ID'] = make_msgid(domain=DNS_NAME)
        for name, value in self.extra_headers.items():
            if name.lower() != 'from':  # From is already handled
                msg[name] = value
        return msg
Exemplo n.º 25
0
    def __init__(self, subject,
                 recipients=None,
                 body=None,
                 html=None,
                 sender=None,
                 cc=None,
                 bcc=None,
                 attachments=None,
                 reply_to=None,
                 date=None,
                 charset=None,
                 extra_headers=None):

        sender = sender or current_app.config.get("DEFAULT_MAIL_SENDER")

        if isinstance(sender, tuple):
            sender = "%s <%s>" % sender

        self.recipients = recipients or []
        self.subject = subject
        self.sender = sender
        self.reply_to = reply_to
        self.cc = cc or []
        self.bcc = bcc or []
        self.body = body
        self.html = html
        self.date = date
        self.msgId = make_msgid()
        self.charset = charset
        self.extra_headers = extra_headers
        self.attachments = attachments or []
Exemplo n.º 26
0
    def test_new_series(self):
        msgid = make_msgid()
        email = self._create_email(msgid)
        project = create_project()

        self.assertIsNone(find_series(project, email,
                                      get_or_create_author(email)))
Exemplo n.º 27
0
def create_email(content, subject=None, sender=None, multipart=False,
                 project=None, content_encoding=None):
    if subject is None:
        subject = defaults.subject
    if sender is None:
        sender = defaults.sender
    if project is None:
        project = defaults.project
        project.save()
    if content_encoding is None:
        content_encoding = 'us-ascii'

    if multipart:
        msg = MIMEMultipart()
        body = MIMEText(content, _subtype='plain',
                        _charset=content_encoding)
        msg.attach(body)
    else:
        msg = MIMEText(content, _charset=content_encoding)

    msg['Message-Id'] = make_msgid()
    msg['Subject'] = subject
    msg['From'] = sender
    msg['List-Id'] = project.listid

    return msg
Exemplo n.º 28
0
def send_notification(to_address, subject, content_text, content_html, uid):
    msg = MIMEMultipart('alternative')

    plain = MIMEText(content_text, 'plain', _charset='utf-8')
    html = MIMEText(transform(content_html), 'html', _charset='utf-8')

    msg.attach(plain)
    msg.attach(html)

    msg['Subject'] = Header(SUBJECT_PREFIX + " " + subject, 'utf-8')
    msg['From'] = config.MAIL_FROM
    msg['To'] = to_address
    msg['Date'] = formatdate(time.time(), localtime=True)
    msg['Message-id'] = make_msgid()
    msg['X-LDAP-ID'] = uid

    logger.info("Mailing %s: '%s'", to_address, subject)
    logger.debug("Content: ---\n%s\n---", content_text)

    if config.NO_MAILS:
        logger.info("skipping mail, because config.NO_MAILS")
        return

    s = smtplib.SMTP(config.MAIL_HOST)
    s.connect(host=config.MAIL_HOST, port=config.MAIL_PORT)
    s.ehlo()
    s.starttls()
    s.login(user=config.MAIL_FROM, password=config.MAIL_PW)
    s.sendmail(config.MAIL_FROM, [to_address], msg.as_string())
    s.quit()
Exemplo n.º 29
0
def create_cover(**kwargs):
    """Create 'CoverLetter' object."""
    num = CoverLetter.objects.count()

    # NOTE(stephenfin): Despite first appearances, passing 'series' to the
    # 'create' function doesn't actually cause the relationship to be created.
    # This is probably a bug in Django. However, it's convenient to do so we
    # emulate that here. For more info, see [1].
    #
    # [1] https://stackoverflow.com/q/43119575/
    series = kwargs.pop('series', None)

    values = {
        'submitter': create_person() if 'person' not in kwargs else None,
        'project': create_project() if 'project' not in kwargs else None,
        'msgid': make_msgid(),
        'name': 'testpatch%d' % num,
        'headers': '',
        'content': '',
    }
    values.update(kwargs)

    cover = CoverLetter.objects.create(**values)

    if series:
        series.add_cover_letter(cover)

    return cover
Exemplo n.º 30
0
def _generate_mail_content(schedule, screenshot, name, url):
    if schedule.delivery_type == EmailDeliveryType.attachment:
        images = None
        data = {
            'screenshot.png': screenshot,
        }
        body = __(
            '<b><a href="%(url)s">Explore in Superset</a></b><p></p>',
            name=name,
            url=url,
        )
    elif schedule.delivery_type == EmailDeliveryType.inline:
        # Get the domain from the 'From' address ..
        # and make a message id without the < > in the ends
        domain = parseaddr(config.get('SMTP_MAIL_FROM'))[1].split('@')[1]
        msgid = make_msgid(domain)[1:-1]

        images = {
            msgid: screenshot,
        }
        data = None
        body = __(
            """
            <b><a href="%(url)s">Explore in Superset</a></b><p></p>
            <img src="cid:%(msgid)s">
            """,
            name=name, url=url, msgid=msgid,
        )

    return EmailContent(body, data, images)
Exemplo n.º 31
0
    def send_msg(self, body, who, subject=None, **kwargs):
        """Sends email and SMS messages.

        **NOTES FOR TARGETING RECIPIENTS WITH 'who':**
            - `'who'` can be a user name, group name, email, or mobile number.
            - It can be an individual item or a list of items.
            - User and group names are defined in ``contact_list.json``.
            - When targeting users or groups, you can toggle the mode of communication using
              `use_email` and `use_sms`. By default, only SMS is used.
            - Mobile numbers can be any format, but they must contain 10 digits in addition to any
              leading 0s or 1s. Integers and strings are OK.

        Arguments:
            body (str): Contents of message.
            who (obj): User name, group name, email, or mobile number. Single items, or a list of many.
                See notes.
            subject (str): Optional. Subject of message. Default is None.

        Keyword Arguments:
            attachment (Path): Path-like object that points to a file.
                Default is None.
            disable_email (bool): If True, emails will not be sent to any recipients.
                This can be useful if you want to send only SMS messages to users or groups in the
                contact_list.json.
                Default is False.
            disable_sms (bool): If True, SMS messages will not be sent to any recipients.
                This can be useful if you want to send only email messages to users or groups in the
                contact_list.json.
                Default is False.

        Returns:
            No returns.
        """

        # ============================================================
        # Parse and bail out if needed
        # ============================================================

        self._parse_who(who)

        if not self._ensure_recipients_exist():
            return

        # Kwargs
        attachment = kwargs.get('attachment', None)
        disable_email = kwargs.get('disable_email', False)
        disable_sms = kwargs.get('disable_sms', False)

        if not self._ensure_attachment_exists(attachment):
            return

        for b, n in zip([disable_email, disable_sms],
                        ['disable_email', 'disable_sms']):
            if not isinstance(b, bool):
                msg = f'\'{n}\' must be boolean but you gave type {type(b)}'
                raise TypeError(msg)

        # ============================================================
        # Main
        # ============================================================

        with self._setup_smtp_server() as sess:

            # Create msg object
            msg = EmailMessage()

            # Personalize the template
            body_from_template = self.template.substitute(BODY=body)

            # Set msg parameters;
            # Note we will assign msg['To'] below when iterating over email addresses
            msg['From'] = self.sender_address
            msg['Subject'] = subject.upper() if isinstance(subject,
                                                           str) else None

            # Copy outgoing emails to cc list
            if isinstance(self.cc_email_list, list):
                if len(self.cc_email_list) > 0:
                    msg['CC'] = ','.join(self.cc_email_list)

            # Base text message
            msg.set_content(body_from_template)

            # HTML version
            body_html = re.sub(r'[\n]', '<br>',
                               body_from_template)  # Replace /n with <br>
            logo_cid = make_msgid()
            msg.add_alternative("""\
            <html>
              <head></head>
              <body>
                <p>""" + body_html + '</p>' + """
                <a href="https://www.liveline.tech">
                <img src="cid:{logo_cid}" />
                </a>
              </body>
            </html>
            """.format(logo_cid=logo_cid[1:-1]),
                                subtype='html')

            # Add logo to the HTML version
            if EMAIL_SIGNATURE_LOGO_FILE is not None:
                t = root / EMAIL_SIGNATURE_LOGO_FILE
                if t.exists():
                    with open(t, 'rb') as img:
                        r = img.read()
                        # noinspection PyUnresolvedReferences
                        msg.get_payload()[1].add_related(r,
                                                         'image',
                                                         'png',
                                                         cid=logo_cid)

            # Optionally attach a file
            # First use mimetypes to try and guess content type based on file extension:
            if attachment is not None:
                attachment = Path(attachment)
                ctype, encoding = mimetypes.guess_type(str(attachment))
                if ctype is None or encoding is not None:
                    # No guess could be made, or the file is encoded (compressed), so
                    # use a generic bag-of-bits type.
                    ctype = 'application/octet-stream'
                maintype, subtype = ctype.split('/', 1)
                maintype += f'; name="{attachment.name}"'
                with open(attachment, 'rb') as file:
                    r = file.read()
                    msg.add_attachment(r, maintype=maintype, subtype=subtype)

            # ============================================================
            # Email
            # ============================================================

            # For each email & phone in current lists, send messages
            if not disable_email:
                for e in self.current_email_list:

                    # Console out
                    stdout_msg = f'COMMUNICATOR MESSAGE: Sending email to: '
                    fancy_print(stdout_msg, fg=COMMUNICATOR_MSG_COLOR, end='')
                    fancy_print(e, fg='hlink')

                    # Update msg 'To:' field
                    if msg['To'] is not None:
                        del msg['To']
                    msg['To'] = e

                    # # Make a local copy of what we are going to send... to a log file?
                    # with open('outgoing.msg', 'wb') as f:
                    #     f.write(bytes(msg))

                    try:
                        sess.send_message(msg)
                    except:
                        stdout_msg = f'COMMUNICATOR WARNING: Failed sending email message'
                        fancy_print(stdout_msg, fg=COMMUNICATOR_WARN_COLOR)

            # ============================================================
            # SMS
            # ============================================================

            if not disable_sms:
                for m in self.current_mobile_list:

                    # Console out
                    stdout_msg = f'COMMUNICATOR MESSAGE: Sending SMS message to: '
                    fancy_print(stdout_msg, fg=COMMUNICATOR_MSG_COLOR, end='')
                    fancy_print(m[0:3] + '.' + m[3:6] + '.' + m[6:10],
                                fg='cerulean')

                    any_ok = False
                    candidates = list()

                    # Try all the stubs!
                    # We don't know the carrier name.
                    # Assume the invalid addresses will get black-holed by the various carriers.
                    for stub in self.sms_email_stubs:
                        candidates.append(m + self.sms_email_stubs[stub])

                    # Update msg 'To:' field
                    if msg['To'] is not None:
                        del msg['To']
                    msg['To'] = candidates

                    # # Make a local copy of what we are going to send... to a log file?
                    # with open('outgoing.msg', 'wb') as f:
                    #     f.write(bytes(msg))

                    try:
                        sess.send_message(msg)
                        any_ok = True
                    except:
                        pass

                    if not any_ok:
                        stdout_msg = f'COMMUNICATOR WARNING: Failed sending SMS message'
                        fancy_print(stdout_msg, fg=COMMUNICATOR_WARN_COLOR)

        return
Exemplo n.º 32
0
# from email.MIMEMultipart import MIMEMultipart
from email.mime.multipart import MIMEMultipart


# from email import Encoders, Utils
from email.utils import formatdate, make_msgid

    # mail['Date'] = Utils.formatdate(localtime=1)
    mail['Date'] = formatdate(localtime=1)

    # mail['Message-ID'] = Utils.make_msgid()
    mail['Message-ID'] = make_msgid()

    # s = smtplib.SMTP(smtp_server, smtp_port)
    s = smtplib.SMTP_SSL(smtp_server, smtp_port)
    def build_email(
        self,
        email_from,
        email_to,
        subject,
        body,
        email_cc=None,
        email_bcc=None,
        reply_to=False,
        attachments=None,
        message_id=None,
        references=None,
        object_id=False,
        subtype="plain",
        headers=None,
        body_alternative=None,
        subtype_alternative="plain",
    ):
        """ copy-pasted from odoo/addons/base/models/ir_mail_server.py::build_email """

        ftemplate = "__image-%s__"
        fcounter = 0
        attachments = attachments or []

        pattern = re.compile(r'"data:image/png;base64,[^"]*"')
        pos = 0
        new_body = ""
        body = body or ""
        while True:
            match = pattern.search(body, pos)
            if not match:
                break
            s = match.start()
            e = match.end()
            data = body[s + len('"data:image/png;base64,'):e - 1]
            new_body += body[pos:s]
            fname = ftemplate % fcounter
            fcounter += 1
            attachments.append((fname, base64.b64decode(data)))

            new_body += '"cid:%s"' % fname
            pos = e

        new_body += body[pos:]
        body = new_body

        email_from = email_from or tools.config.get("email_from")
        assert email_from, (
            "You must either provide a sender address explicitly or configure "
            "a global sender address in the server configuration or with the "
            "--email-from startup parameter.")

        # Note: we must force all strings to to 8-bit utf-8 when crafting message,
        #       or use encode_header() for headers, which does it automatically.

        headers = headers or {}  # need valid dict later

        if not email_cc:
            email_cc = []
        if not email_bcc:
            email_bcc = []
        if not body:
            body = u""

        email_body_utf8 = ustr(body).encode("utf-8")
        email_text_part = MIMEText(email_body_utf8,
                                   _subtype=subtype,
                                   _charset="utf-8")
        msg = MIMEMultipart()

        if not message_id:
            if object_id:
                message_id = tools.generate_tracking_message_id(object_id)
            else:
                message_id = make_msgid()
        msg["Message-Id"] = encode_header(message_id)
        if references:
            msg["references"] = encode_header(references)
        msg["Subject"] = encode_header(subject)
        msg["From"] = encode_rfc2822_address_header(email_from)
        del msg["Reply-To"]
        if reply_to:
            msg["Reply-To"] = encode_rfc2822_address_header(reply_to)
        else:
            msg["Reply-To"] = msg["From"]
        msg["To"] = encode_rfc2822_address_header(COMMASPACE.join(email_to))
        if email_cc:
            msg["Cc"] = encode_rfc2822_address_header(
                COMMASPACE.join(email_cc))
        if email_bcc:
            msg["Bcc"] = encode_rfc2822_address_header(
                COMMASPACE.join(email_bcc))
        msg["Date"] = formatdate()
        # Custom headers may override normal headers or provide additional ones
        for key, value in headers.items():
            msg[ustr(key).encode("utf-8")] = encode_header(value)

        if subtype == "html" and not body_alternative and html2text:
            # Always provide alternative text body ourselves if possible.
            text_utf8 = tools.html2text(
                email_body_utf8.decode("utf-8")).encode("utf-8")
            alternative_part = MIMEMultipart(_subtype="alternative")
            alternative_part.attach(
                MIMEText(text_utf8, _charset="utf-8", _subtype="plain"))
            alternative_part.attach(email_text_part)
            msg.attach(alternative_part)
        elif body_alternative:
            # Include both alternatives, as specified, within a multipart/alternative part
            alternative_part = MIMEMultipart(_subtype="alternative")
            body_alternative_utf8 = ustr(body_alternative).encode("utf-8")
            alternative_body_part = MIMEText(body_alternative_utf8,
                                             _subtype=subtype_alternative,
                                             _charset="utf-8")
            alternative_part.attach(alternative_body_part)
            alternative_part.attach(email_text_part)
            msg.attach(alternative_part)
        else:
            msg.attach(email_text_part)

        if attachments:
            for (fname, fcontent, mime) in attachments:
                filename_rfc2047 = encode_header_param(fname)
                if mime and "/" in mime:
                    maintype, subtype = mime.split("/", 1)
                    part = MIMEBase(maintype, subtype)
                else:
                    part = MIMEBase("application", "octet-stream")

                # The default RFC2231 encoding of Message.add_header() works in Thunderbird but not GMail
                # so we fix it by using RFC2047 encoding for the filename instead.
                part.sudo().set_param("name", filename_rfc2047)
                part.add_header("Content-Disposition",
                                "attachment",
                                filename=filename_rfc2047)
                part.add_header("Content-ID",
                                "<%s>" % filename_rfc2047)  # NEW STUFF

                part.set_payload(fcontent)
                encoders.encode_base64(part)
                msg.attach(part)
        return msg
Exemplo n.º 34
0
def sending_email(recipients, sender_name, sender_email, subject, body,
                  body_txt, files, cclist, bcclist, email_server,
                  dkim_private_path, dkim_selector):
    msg = MIMEMultipart()
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = six.text_type(subject)
    msg['To'] = ", ".join(recipients)
    if isinstance(cclist, list):
        cclist = split_doubled_email(cclist)
        for recipient in recipients:
            if recipient in cclist:
                cclist.remove(recipient)

        msg['Cc'] = ", ".join(cclist)
        recipients.extend(cclist)
    if isinstance(bcclist, list):
        bcclist = split_doubled_email(bcclist)
        for recipient in recipients:
            if recipient in bcclist:
                bcclist.remove(recipient)
        recipients.extend(bcclist)

    domain = sender_email.split('@')[-1]
    msg_from = "%s <%s>" % (sender_name, sender_email)
    msg['From'] = msg_from
    msg['Organization'] = sender_name
    msg['Return-Path'] = sender_email
    msg['Reply-To'] = sender_email
    msg['Message-ID'] = make_msgid(domain=domain)
    body = six.text_type(body).strip()
    if body[:6].lower() == '<html>':
        if body_txt is None:
            h2txt = HTML2Text()
            h2txt.ignore_links = False
            h2txt.wrap_links = False
            body_txt = h2txt.handle(body)
        msg_alternative = MIMEMultipart('alternative')
        msg_alternative.attach(MIMEText(body, 'html', 'utf-8'))
        msg_alternative.attach(MIMEText(body_txt, 'plain', 'utf-8'))
        msg.attach(msg_alternative)
    else:
        msg.attach(MIMEText(body, 'plain', 'utf-8'))
    if (files is not None) and (len(files) > 0):
        for filename, file in files:
            msg.attach(
                MIMEApplication(
                    file.read(),
                    Content_Disposition='attachment; filename="%s"' % filename,
                    Name=filename))

    if (dkim_private_path !=
            '') and isfile(dkim_private_path) and (dkim_selector != ''):
        import dkim
        with open(dkim_private_path) as dkim_private_file:
            privateKey = dkim_private_file.read()
        headers = [b'from', b'to', b'subject']
        sig = dkim.sign(msg.as_string().encode(),
                        dkim_selector.encode(),
                        domain.encode(),
                        privateKey.encode(),
                        include_headers=headers)
        sig = sig.decode()
        msg['DKIM-Signature'] = sig[len("DKIM-Signature: "):]

    try:
        return email_server.sendmail(msg_from, recipients, msg.as_string())
    except Exception as error:
        raise EmailException(six.text_type(error))
    finally:
        if email_server:
            email_server.quit()
Exemplo n.º 35
0
from email.utils import make_msgid

server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()

username = ""
password = ""
server.login(username, password)

FROM = "*****@*****.**"  #<from-address>
TO = "*****@*****.**"  #[<to-addres>]
SUBJECT = "Hello!"
TEXT = "This message was sent with Python's smtplib."
message = 'Subject: {}\n\n{}'.format(SUBJECT, TEXT)
message = EmailMessage()
asparagus_cid = make_msgid()
message['Subject'] = "This is a test msg"
message['From'] = Address("Jimut", "Jimut", "*****@*****.**")
message['To'] = (Address("Jimut B.", "Jimut1", "*****@*****.**"),
                 Address("Jimut B. Pal", "Jimut", "*****@*****.**"))
message.set_content("""\
Rse!

Cela ressemble à un excellent recipie[1] déjeuner.

[1] http://www.yummly.com/recipe/Roasted-Asparagus-Epicurious-203718

--Pepé
""")
message.add_alternative("""\
<html>
from email import utils, encoders
import mimetypes, sys


def alternative(data, contenttype):
    maintype, subtype = contenttype.split('/')
    if maintype == 'text':
        retival = MIMEText(data, _subtype=subtype)
    else:
        retival = MIMEBase(maintype, subtype)
        retival.set_payload(data)
        encoders.encode_base64(retival)
    return retival


messagetext = """Hello,
This is a *great* test message from chapter 9. I hope you enjoy it!
-- Anonymous"""
messagehtml = """Hello, <p>
This is a <b>great</b> test message from Chapter 9. I hope you enjoy it!</p>
-- <i>Anonymous</i>"""

msg = MIMEMultipart('alternative')
msg['TO'] = '*****@*****.**'
msg['From'] = 'Test Sender <*****@*****.**>'
msg['Subject'] = 'Test Message, Chapter 9'
msg['Date'] = utils.formatdate(localtime=1)
msg['Message-ID'] = utils.make_msgid()
msg.attach(alternative(messagetext, 'text/plain'))
msg.attach(alternative(messagehtml, 'text/html'))
print(msg.as_bytes().decode())
Exemplo n.º 37
0
def build_msg_html_image(*args):
    '''
    用户需要依次传入 subject, receiver, html, [ image | start_time, end_time, idc_name ] 等参数,
    其他参数都是默认的,也可以在本函数中自行修改。
    '''
    # 解析参数
    subject = args[0]
    receiver = args[1]
    html = args[2]
    if len(args) == 4:
        image = args[3]
    elif len(args) == 6:
        start_time = args[3]
        end_time = args[4]
        idc_name = args[5]
    else:
        print('invalid args, please check!')
        exit(2)

    ## 下面参数请根据实际需要修改
    sender = '*****@*****.**'
    # cc = ['*****@*****.**']
    # bcc = ['*****@*****.**']
    msg = MIMEMultipart('alternative')
    msg['Subject'] = Header(subject, 'utf-8')
    msg['From'] = formataddr(['易网信Robot ', sender])
    msg['To'] = ','.join(receiver)
    # 根据实际情况决定 抄送,暗送
    # msg['Cc'] = ','.join(cc)
    # msg['Bcc'] = ','.join(bcc)
    msg['Message-id'] = make_msgid()
    msg['Date'] = formatdate(localtime=1)

    ## 下面参数请根据实际需要修改
    image_logo = "image/logo.jpg"
    image_logo_id = 'image_logo_id'
    with open(image_logo, "rb") as f:
        logo = MIMEImage(f.read())
        f.close()
    logo.add_header('Content-ID', image_logo_id)
    msg.attach(logo)

    ## 下面参数请根据实际需要修改
    html_footer = 'html_footer.txt'
    f = open(html_footer, 'rb')
    html_footer = f.read().decode() % (image_logo_id)
    f.close()

    f = open(html, 'rb')
    if len(args) == 4:
        image_id = 'image_id'
        with open(image, "rb") as f2:
            new_year = MIMEImage(f2.read())
            f2.close()
        new_year.add_header('Content-ID', image_id)
        msg.attach(new_year)
        html = f.read().decode() % (image_id, html_footer)
    elif len(args) == 6:
        html = f.read().decode() % (idc_name, start_time, end_time,
                                    html_footer)
    f.close()

    msg_html_image = MIMEText(html, 'html', 'utf-8')
    msg.attach(msg_html_image)

    return msg
Exemplo n.º 38
0
    def build_email(self,
                    email_from,
                    email_to,
                    subject,
                    body,
                    email_cc=None,
                    email_bcc=None,
                    reply_to=False,
                    attachments=None,
                    message_id=None,
                    references=None,
                    object_id=False,
                    subtype='plain',
                    headers=None,
                    body_alternative=None,
                    subtype_alternative='plain'):
        """Constructs an RFC2822 email.message.Message object based on the keyword arguments passed, and returns it.

           :param string email_from: sender email address
           :param list email_to: list of recipient addresses (to be joined with commas) 
           :param string subject: email subject (no pre-encoding/quoting necessary)
           :param string body: email body, of the type ``subtype`` (by default, plaintext).
                               If html subtype is used, the message will be automatically converted
                               to plaintext and wrapped in multipart/alternative, unless an explicit
                               ``body_alternative`` version is passed.
           :param string body_alternative: optional alternative body, of the type specified in ``subtype_alternative``
           :param string reply_to: optional value of Reply-To header
           :param string object_id: optional tracking identifier, to be included in the message-id for
                                    recognizing replies. Suggested format for object-id is "res_id-model",
                                    e.g. "12345-crm.lead".
           :param string subtype: optional mime subtype for the text body (usually 'plain' or 'html'),
                                  must match the format of the ``body`` parameter. Default is 'plain',
                                  making the content part of the mail "text/plain".
           :param string subtype_alternative: optional mime subtype of ``body_alternative`` (usually 'plain'
                                              or 'html'). Default is 'plain'.
           :param list attachments: list of (filename, filecontents) pairs, where filecontents is a string
                                    containing the bytes of the attachment
           :param list email_cc: optional list of string values for CC header (to be joined with commas)
           :param list email_bcc: optional list of string values for BCC header (to be joined with commas)
           :param dict headers: optional map of headers to set on the outgoing mail (may override the
                                other headers, including Subject, Reply-To, Message-Id, etc.)
           :rtype: email.message.Message (usually MIMEMultipart)
           :return: the new RFC2822 email message
        """
        email_from = email_from or self._get_default_from_address()
        assert email_from, "You must either provide a sender address explicitly or configure "\
                           "using the combintion of `mail.catchall.domain` and `mail.default.from` "\
                           "ICPs, in the server configuration file or with the "\
                           "--email-from startup parameter."

        # Note: we must force all strings to to 8-bit utf-8 when crafting message,
        #       or use encode_header() for headers, which does it automatically.

        headers = headers or {}  # need valid dict later
        email_cc = email_cc or []
        email_bcc = email_bcc or []
        body = body or u''

        email_body = ustr(body)
        email_text_part = MIMEText(email_body,
                                   _subtype=subtype,
                                   _charset='utf-8')
        msg = MIMEMultipart()

        if not message_id:
            if object_id:
                message_id = tools.generate_tracking_message_id(object_id)
            else:
                message_id = make_msgid()
        msg['Message-Id'] = encode_header(message_id)
        if references:
            msg['references'] = encode_header(references)
        msg['Subject'] = encode_header(subject)
        msg['From'] = encode_rfc2822_address_header(email_from)
        del msg['Reply-To']
        if reply_to:
            msg['Reply-To'] = encode_rfc2822_address_header(reply_to)
        else:
            msg['Reply-To'] = msg['From']
        msg['To'] = encode_rfc2822_address_header(COMMASPACE.join(email_to))
        if email_cc:
            msg['Cc'] = encode_rfc2822_address_header(
                COMMASPACE.join(email_cc))
        if email_bcc:
            msg['Bcc'] = encode_rfc2822_address_header(
                COMMASPACE.join(email_bcc))
        msg['Date'] = formatdate()
        # Custom headers may override normal headers or provide additional ones
        for key, value in headers.items():
            msg[pycompat.to_text(ustr(key))] = encode_header(value)

        if subtype == 'html' and not body_alternative:
            # Always provide alternative text body ourselves if possible.
            text = html2text.html2text(email_body)
            alternative_part = MIMEMultipart(_subtype="alternative")
            alternative_part.attach(
                MIMEText(text, _charset='utf-8', _subtype='plain'))
            alternative_part.attach(email_text_part)
            msg.attach(alternative_part)
        elif body_alternative:
            # Include both alternatives, as specified, within a multipart/alternative part
            alternative_part = MIMEMultipart(_subtype="alternative")
            body_alternative_ = ustr(body_alternative)
            alternative_body_part = MIMEText(body_alternative_,
                                             _subtype=subtype_alternative,
                                             _charset='utf-8')
            alternative_part.attach(alternative_body_part)
            alternative_part.attach(email_text_part)
            msg.attach(alternative_part)
        else:
            msg.attach(email_text_part)

        if attachments:
            for (fname, fcontent, mime) in attachments:
                filename_rfc2047 = encode_header_param(fname)
                if mime and '/' in mime:
                    maintype, subtype = mime.split('/', 1)
                    part = MIMEBase(maintype, subtype)
                else:
                    part = MIMEBase('application', "octet-stream")

                # The default RFC2231 encoding of Message.add_header() works in Thunderbird but not GMail
                # so we fix it by using RFC2047 encoding for the filename instead.
                part.set_param('name', filename_rfc2047)
                part.add_header('Content-Disposition',
                                'attachment',
                                filename=filename_rfc2047)

                part.set_payload(fcontent)
                encoders.encode_base64(part)
                msg.attach(part)
        return msg
Exemplo n.º 39
0
def create(sender, recipients=None, cc=None, bcc=None, subject='', message='',
           html_message='', context=None, scheduled_time=None, expires_at=None, headers=None,
           template=None, priority=None, render_on_delivery=False, commit=True,
           backend=''):
    """
    Creates an email from supplied keyword arguments. If template is
    specified, email subject and content will be rendered during delivery.
    """
    priority = parse_priority(priority)
    status = None if priority == PRIORITY.now else STATUS.queued

    if recipients is None:
        recipients = []
    if cc is None:
        cc = []
    if bcc is None:
        bcc = []
    if context is None:
        context = ''
    message_id = make_msgid(domain=get_message_id_fqdn()) if get_message_id_enabled() else None

    # If email is to be rendered during delivery, save all necessary
    # information
    if render_on_delivery:
        email = Email(
            from_email=sender,
            to=recipients,
            cc=cc,
            bcc=bcc,
            scheduled_time=scheduled_time,
            expires_at=expires_at,
            message_id=message_id,
            headers=headers, priority=priority, status=status,
            context=context, template=template, backend_alias=backend
        )

    else:

        if template:
            subject = template.subject
            message = template.content
            html_message = template.html_content

        _context = Context(context or {})
        subject = Template(subject).render(_context)
        message = Template(message).render(_context)
        html_message = Template(html_message).render(_context)

        email = Email(
            from_email=sender,
            to=recipients,
            cc=cc,
            bcc=bcc,
            subject=subject,
            message=message,
            html_message=html_message,
            scheduled_time=scheduled_time,
            expires_at=expires_at,
            message_id=message_id,
            headers=headers, priority=priority, status=status,
            backend_alias=backend
        )

    if commit:
        email.save()

    return email
    def build_email(self,
                    email_from,
                    email_to,
                    subject,
                    body,
                    email_cc=None,
                    email_bcc=None,
                    reply_to=False,
                    attachments=None,
                    message_id=None,
                    references=None,
                    object_id=False,
                    subtype='plain',
                    headers=None,
                    body_alternative=None,
                    subtype_alternative='plain'):
        """Constructs an RFC2822 email.message.Message object based on the keyword arguments passed, and returns it.

           :param string email_from: sender email address
           :param list email_to: list of recipient addresses (to be joined with commas)
           :param string subject: email subject (no pre-encoding/quoting necessary)
           :param string body: email body, of the type ``subtype`` (by default, plaintext).
                               If html subtype is used, the message will be automatically converted
                               to plaintext and wrapped in multipart/alternative, unless an explicit
                               ``body_alternative`` version is passed.
           :param string body_alternative: optional alternative body, of the type specified in ``subtype_alternative``
           :param string reply_to: optional value of Reply-To header
           :param string object_id: optional tracking identifier, to be included in the message-id for
                                    recognizing replies. Suggested format for object-id is "res_id-model",
                                    e.g. "12345-crm.lead".
           :param string subtype: optional mime subtype for the text body (usually 'plain' or 'html'),
                                  must match the format of the ``body`` parameter. Default is 'plain',
                                  making the content part of the mail "text/plain".
           :param string subtype_alternative: optional mime subtype of ``body_alternative`` (usually 'plain'
                                              or 'html'). Default is 'plain'.
           :param list attachments: list of (filename, filecontents) pairs, where filecontents is a string
                                    containing the bytes of the attachment
           :param list email_cc: optional list of string values for CC header (to be joined with commas)
           :param list email_bcc: optional list of string values for BCC header (to be joined with commas)
           :param dict headers: optional map of headers to set on the outgoing mail (may override the
                                other headers, including Subject, Reply-To, Message-Id, etc.)
           :rtype: email.message.EmailMessage
           :return: the new RFC2822 email message
        """
        email_from = email_from or self._get_default_from_address()
        assert email_from, "You must either provide a sender address explicitly or configure "\
                           "using the combintion of `mail.catchall.domain` and `mail.default.from` "\
                           "ICPs, in the server configuration file or with the "\
                           "--email-from startup parameter."

        headers = headers or {}  # need valid dict later
        email_cc = email_cc or []
        email_bcc = email_bcc or []
        body = body or u''

        msg = EmailMessage(policy=email.policy.SMTP)
        msg.set_charset('utf-8')

        if not message_id:
            if object_id:
                message_id = tools.generate_tracking_message_id(object_id)
            else:
                message_id = make_msgid()
        msg['Message-Id'] = message_id
        if references:
            msg['references'] = references
        msg['Subject'] = subject
        msg['From'] = email_from
        del msg['Reply-To']
        msg['Reply-To'] = reply_to or email_from
        msg['To'] = email_to
        if email_cc:
            msg['Cc'] = email_cc
        if email_bcc:
            msg['Bcc'] = email_bcc
        msg['Date'] = datetime.datetime.utcnow()
        for key, value in headers.items():
            msg[pycompat.to_text(ustr(key))] = value

        email_body = ustr(body)
        if subtype == 'html' and not body_alternative:
            msg.add_alternative(html2text.html2text(email_body),
                                subtype='plain',
                                charset='utf-8')
            msg.add_alternative(email_body, subtype=subtype, charset='utf-8')
        elif body_alternative:
            msg.add_alternative(ustr(body_alternative),
                                subtype=subtype_alternative,
                                charset='utf-8')
            msg.add_alternative(email_body, subtype=subtype, charset='utf-8')
        else:
            msg.set_content(email_body, subtype=subtype, charset='utf-8')

        if attachments:
            for (fname, fcontent, mime) in attachments:
                maintype, subtype = mime.split(
                    '/') if mime and '/' in mime else ('application',
                                                       'octet-stream')
                msg.add_attachment(fcontent, maintype, subtype, filename=fname)
        return msg
Exemplo n.º 41
0
def send_email(subject, body, recipients, sender=None, bcc=None, attempts=3):
    """Send email.

    subject: email's subject
    body: email's body
    recipients: an email address as a string or an iterable of email addresses
    sender: the email address of the sender. default value taken from config

    """
    if isinstance(subject, str):
        subject = subject.decode('utf-8', 'ignore')

    if not sender:
        sender = config.EMAIL_FROM
    if isinstance(recipients, basestring):
        recipients = [recipients]
    headers = [
        "From: %s" % sender,
        "To: %s" % ", ".join(recipients),
        "Subject: %s" % subject,
        "Date: %s" % formatdate(),
        "Message-ID: %s" % make_msgid()
    ]
    if bcc:
        headers.append("Bcc: %s" % bcc)
        recipients.append(bcc)

    if isinstance(body, str):
        body = body.decode('utf8')

    message = "%s\r\n\r\n%s" % ("\r\n".join(headers), body)
    message = message.encode('utf-8', 'ignore')

    mail_settings = config.MAILER_SETTINGS
    host = mail_settings.get('mail.host')
    port = mail_settings.get('mail.port', '5555')
    username = mail_settings.get('mail.username')
    password = mail_settings.get('mail.password')
    tls = mail_settings.get('mail.tls')
    starttls = mail_settings.get('mail.starttls')

    # try 3 times to circumvent network issues
    for attempt in range(attempts):
        try:
            if tls and not starttls:
                server = smtplib.SMTP_SSL(host, port)
            else:
                server = smtplib.SMTP(host, port)
            if tls and starttls:
                server.starttls()
            if username:
                server.login(username, password)

            ret = server.sendmail(sender, recipients, message)
            server.quit()
            return True
        except smtplib.SMTPException as exc:
            if attempt == attempts - 1:
                log.error("Could not send email after %d retries! Error: %r",
                          attempts, exc)
                return False
            else:
                log.warn("Could not send email! Error: %r", exc)
                log.warn("Retrying in 5 seconds...")
                sleep(5)
Exemplo n.º 42
0
 def __init__(self, message):
     self.message = message
     self.message_id = message.message_id or make_msgid()
     self.references = message.references
Exemplo n.º 43
0
def message_id_generator():
    rstring = ''.join(random.choice(string.ascii_letters) for x in range(13))
    return make_msgid(domain='mail.gmail.com', idstring=rstring)
Exemplo n.º 44
0
    def send_raw_email(self):
        self.queue[self.current]['starttime'] = datetime.now()
        self.UIqueue[self.current]['formStarttime'] = self.queue[
            self.current]['starttime']
        self.queue[self.current]['status'] = STAT_STARTED
        self.UIqueue[self.current]['status'] = _('Started')
        obj = self.queue[self.current]
        # create MIME message
        msg = MIMEMultipart()
        msg['Subject'] = self.queue[self.current]['subject']
        msg['Message-Id'] = make_msgid('calibre-web')
        msg['Date'] = formatdate(localtime=True)
        text = self.queue[self.current]['text']
        msg.attach(MIMEText(text.encode('UTF-8'), 'plain', 'UTF-8'))
        if obj['attachment']:
            result = get_attachment(obj['filepath'], obj['attachment'])
            if result:
                msg.attach(result)
            else:
                self._handleError(u"Attachment not found")
                return

        msg['From'] = obj['settings']["mail_from"]
        msg['To'] = obj['recipent']

        use_ssl = int(obj['settings'].get('mail_use_ssl', 0))
        try:
            # convert MIME message to string
            fp = StringIO()
            gen = Generator(fp, mangle_from_=False)
            gen.flatten(msg)
            msg = fp.getvalue()

            # send email
            timeout = 600  # set timeout to 5mins

            org_stderr = sys.stderr
            sys.stderr = StderrLogger()

            if use_ssl == 2:
                self.asyncSMTP = email_SSL(obj['settings']["mail_server"],
                                           obj['settings']["mail_port"],
                                           timeout)
            else:
                self.asyncSMTP = email(obj['settings']["mail_server"],
                                       obj['settings']["mail_port"], timeout)

            # link to logginglevel
            if web.ub.config.config_log_level != logging.DEBUG:
                self.asyncSMTP.set_debuglevel(0)
            else:
                self.asyncSMTP.set_debuglevel(1)
            if use_ssl == 1:
                self.asyncSMTP.starttls()
            if obj['settings']["mail_password"]:
                self.asyncSMTP.login(str(obj['settings']["mail_login"]),
                                     str(obj['settings']["mail_password"]))
            self.asyncSMTP.sendmail(obj['settings']["mail_from"],
                                    obj['recipent'], msg)
            self.asyncSMTP.quit()
            self._handleSuccess()
            sys.stderr = org_stderr

        except (MemoryError) as e:
            self._handleError(u'Error sending email: ' + e.message)
            return None
        except (smtplib.SMTPException) as e:
            self._handleError(u'Error sending email: ' +
                              e.smtp_error.replace("\n", '. '))
            return None
        except (socket.error) as e:
            self._handleError(u'Error sending email: ' + e.strerror)
            return None