Example #1
0
    def mimemelding(self):
        m = MIMEMultipart()
        m['Subject'] = Header(self.tittel, self.charset)
        n = self.ordre.firma.firmanavn.replace(';', ' ').replace(',',' ')
        m['From'] = '"%s" <%s>' % (Header(n, self.charset), self.fra)
        #m['To'] = '"%s" <%s>' % (Header(self.ordre.kunde.navn, self.charset), self.til)
        m['To'] = self.til #'"%s" <%s>' % (Header(self.ordre.kunde.navn, self.charset), self.til)
        m.preamble = 'You will not see this in a MIME-aware mail reader.\n'
        # To guarantee the message ends with a newline
        m.epilogue = ''

        # Legg til tekstlig informasjon
        t = MIMEText(self.tekst.encode(self.charset), 'plain', self.charset)
        m.attach(t)

        # Legg til fakturaen
        b = MIMEBase('application', 'x-pdf')
        _filename=Header('%s-%i.pdf' % (self.ordre.firma.firmanavn, self.ordre.ID), self.charset)
        b.add_header('Content-Disposition', 'attachment', filename=_filename.encode()) # legg til filnavn
        m.attach(b)
        fp = open(self.pdfFilnavn, 'rb')
        b.set_payload(fp.read()) # les inn fakturaen
        fp.close()
        encoders.encode_base64(b) #base64 encode subpart

        # Legg til vedlegg
        for filnavn, vedlegg in self.vedlegg:
            v = MIMEBase('application', 'octet-stream')
            _filename=Header(filnavn, self.charset)
            v.add_header('Content-Disposition', 'attachment', filename=_filename.encode()) # legg til filnavn
            m.attach(v)
            v.set_payload(vedlegg) 
            encoders.encode_base64(v) #base64 encode subpart

        return m
    def test_japanese_codecs(self):
        eq = self.ndiffAssertEqual
        j = Charset("euc-jp")
        g = Charset("iso-8859-1")
        h = Header("Hello World!")
        jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa'
        ghello = 'Gr\xfc\xdf Gott!'
        h.append(jhello, j)
        h.append(ghello, g)
        # BAW: This used to -- and maybe should -- fold the two iso-8859-1
        # chunks into a single encoded word.  However it doesn't violate the
        # standard to have them as two encoded chunks and maybe it's
        # reasonable <wink> for each .append() call to result in a separate
        # encoded word.
        eq(h.encode(), """\
Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?=
 =?iso-8859-1?q?Gr=FC=DF?= =?iso-8859-1?q?_Gott!?=""")
        eq(decode_header(h.encode()),
           [('Hello World!', None),
            ('\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'),
            ('Gr\xfc\xdf Gott!', 'iso-8859-1')])
        long = 'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9'
        h = Header(long, j, header_name="Subject")
        # test a very long header
        enc = h.encode()
        # TK: splitting point may differ by codec design and/or Header encoding
        eq(enc , """\
=?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYSE8JWskTztKGyhC?=
 =?iso-2022-jp?b?GyRCMnE8VCROPjVHJyRyQlQkQyRGJCQkXiQ5GyhC?=""")
        # TK: full decode comparison
        eq(h.__unicode__().encode('euc-jp'), long)
Example #3
0
def format_str(s): # encode if contain utf-8 or else cannot be correctly dispalyed
	name,addr = parseaddr(s)
	print 'name:',name,'addr:',addr

	head = Header(name,'utf-8')
	print 'head:',head,'encode:',head.encode()
	print 'addr encode:',addr.encode()

	return formataddr((head.encode(),addr.encode()))
Example #4
0
File: utils.py Project: windo/alot
def encode_header(key, value):
    """
    encodes a unicode string as a valid header value

    :param key: the header field this value will be stored in
    :type key: str
    :param value: the value to be encoded
    :type value: unicode
    """
    # handle list of "realname <email>" entries separately
    if key.lower() in ['from', 'to', 'cc', 'bcc']:
        rawentries = value.split(',')
        encodedentries = []
        for entry in rawentries:
            m = re.search('\s*(.*)\s+<(.*\@.*\.\w*)>\s*$', entry)
            if m:  # If a realname part is contained
                name, address = m.groups()
                # try to encode as ascii, if that fails, revert to utf-8
                # name must be a unicode string here
                namepart = Header(name)
                # append address part encoded as ascii
                entry = '%s <%s>' % (namepart.encode(), address)
            encodedentries.append(entry)
        value = Header(', '.join(encodedentries))
    else:
        value = Header(value)
    return value
Example #5
0
File: mail.py Project: whausen/part
def to_mail(to_name, to_email, subject, body, headers={}, decorate_body=True,
            email_from=None, name_from=None):
    try:
        if email_from is None:
            email_from = config.get('adhocracy.email.from')
        if name_from is None:
            name_from = config.get('adhocracy.site.name')

        if decorate_body:
            body = (_(u"Hi %s,") % to_name +
                    u"\r\n\r\n%s\r\n\r\n" % body +
                    _(u"Cheers,\r\n\r\n"
                      u"    the %s Team\r\n") %
                    config.get('adhocracy.site.name'))

        msg = MIMEText(body.encode(ENCODING), 'plain', ENCODING)

        for k, v in headers.items():
            msg[k] = v

        subject = Header(subject.encode(ENCODING), ENCODING)
        msg['Subject'] = subject
        msg['From'] = _("%s <%s>") % (name_from, email_from)
        to = Header(u"%s <%s>" % (to_name, to_email), ENCODING)
        msg['To'] = to
        msg['Date'] = email.Utils.formatdate(time())
        msg['X-Mailer'] = "Adhocracy SMTP %s" % version.get_version()
        #log.debug("MAIL\r\n" + msg.as_string())
        send(email_from, to_email, msg.as_string())
    except Exception:
        log.exception("Sending mail failed.")
Example #6
0
 def _write_headers(self, msg):
     # This is almost the same as the string version, except for handling
     # strings with 8bit bytes.
     for h, v in msg._headers:
         self.write('%s: ' % h)
         if isinstance(v, str):
             if _has_surrogates(v):
                 if not self.policy.must_be_7bit:
                     # If we have raw 8bit data in a byte string, we have no idea
                     # what the encoding is.  There is no safe way to split this
                     # string.  If it's ascii-subset, then we could do a normal
                     # ascii split, but if it's multibyte then we could break the
                     # string.  There's no way to know so the least harm seems to
                     # be to not split the string and risk it being too long.
                     self.write(v+NL)
                     continue
                 h = Header(v, charset=_charset.UNKNOWN8BIT, header_name=h)
             else:
                 h = Header(v, header_name=h)
         else:
             # Assume it is a Header-like object.
             h = v
         self.write(h.encode(linesep=self._NL,
                             maxlinelen=self._maxheaderlen)+self._NL)
     # A blank line always separates headers from body
     self.write(self._NL)
Example #7
0
def encode_param(key, name, value):
    try:
        value = value.encode("ascii")
        return email.message._formatparam(name, value)
    except Exception:
        value = Header(value.encode("utf-8"), "utf-8",  header_name=key).encode(splitchars=' ;,')
        return email.message._formatparam(name, value)
Example #8
0
def to_mail(to_name, to_email, subject, body, headers={}, decorate_body=True):
    try:
        email_from = config.get("adhocracy.email.from")

        if decorate_body:
            body = (
                _(u"Hi %s,") % to_name
                + u"\r\n\r\n%s\r\n\r\n" % body
                + _(u"Cheers,\r\n\r\n" u"    the %s Team\r\n") % config.get("adhocracy.site.name")
            )

        msg = MIMEText(body.encode(ENCODING), "plain", ENCODING)

        for k, v in headers.items():
            msg[k] = v

        subject = Header(subject.encode(ENCODING), ENCODING)
        msg["Subject"] = subject
        msg["From"] = _("%s <%s>") % (config.get("adhocracy.site.name"), email_from)
        to = Header(u"%s <%s>" % (to_name, to_email), ENCODING)
        msg["To"] = to
        msg["Date"] = email.Utils.formatdate(time())
        msg["X-Mailer"] = "Adhocracy SMTP %s" % version.get_version()
        # log.debug("MAIL\r\n" + msg.as_string())
        send(email_from, to_email, msg.as_string())
    except Exception:
        log.exception("Sending mail failed.")
Example #9
0
def _mail_recipient(recipient_name, recipient_email,
        sender_name, sender_url, subject,
        body, headers={}):
    mail_from = config.get('ckan.mail_from')
    body = add_msg_niceties(recipient_name, body, sender_name, sender_url)
    msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
    for k, v in headers.items(): msg[k] = v
    subject = Header(subject.encode('utf-8'), 'utf-8')
    msg['Subject'] = subject
    msg['From'] = _("%s <%s>") % (sender_name, mail_from)
    recipient = u"%s <%s>" % (recipient_name, recipient_email)
    msg['To'] = Header(recipient, 'utf-8')
    msg['Date'] = Utils.formatdate(time())
    msg['X-Mailer'] = "CKAN %s" % __version__
    try:
        server = smtplib.SMTP(
            config.get('test_smtp_server',
                       config.get('smtp_server', 'localhost')))
        #server.set_debuglevel(1)
        server.sendmail(mail_from, [recipient_email], msg.as_string())
        server.quit()
    except Exception, e:
        msg = '%r' % e
        log.exception(msg)
        raise MailerException(msg)
Example #10
0
def _mail_recipient(recipient_name, recipient_email,
        sender_name, sender_url, subject,
        body, headers={}):
    mail_from = config.get('smtp.mail_from')
    body = add_msg_niceties(recipient_name, body, sender_name, sender_url)
    msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
    for k, v in headers.items(): msg[k] = v
    subject = Header(subject.encode('utf-8'), 'utf-8')
    msg['Subject'] = subject
    msg['From'] = _("%s <%s>") % (sender_name, mail_from)
    recipient = u"%s <%s>" % (recipient_name, recipient_email)
    msg['To'] = Header(recipient, 'utf-8')
    msg['Date'] = Utils.formatdate(time())
    msg['X-Mailer'] = "CKAN %s" % ckan.__version__

    # Send the email using Python's smtplib.
    smtp_connection = smtplib.SMTP()
    if 'smtp.test_server' in config:
        # If 'smtp.test_server' is configured we assume we're running tests,
        # and don't use the smtp.server, starttls, user, password etc. options.
        smtp_server = config['smtp.test_server']
        smtp_starttls = False
        smtp_user = None
        smtp_password = None
    else:
        smtp_server = config.get('smtp.server', 'localhost')
        smtp_starttls = paste.deploy.converters.asbool(
                config.get('smtp.starttls'))
        smtp_user = config.get('smtp.user')
        smtp_password = config.get('smtp.password')
    smtp_connection.connect(smtp_server)
    try:
        #smtp_connection.set_debuglevel(True)

        # Identify ourselves and prompt the server for supported features.
        smtp_connection.ehlo()

        # If 'smtp.starttls' is on in CKAN config, try to put the SMTP
        # connection into TLS mode.
        if smtp_starttls:
            if smtp_connection.has_extn('STARTTLS'):
                smtp_connection.starttls()
                # Re-identify ourselves over TLS connection.
                smtp_connection.ehlo()
            else:
                raise MailerException("SMTP server does not support STARTTLS")

        # If 'smtp.user' is in CKAN config, try to login to SMTP server.
        if smtp_user:
            assert smtp_password, ("If smtp.user is configured then "
                    "smtp.password must be configured as well.")
            smtp_connection.login(smtp_user, smtp_password)

        smtp_connection.sendmail(mail_from, [recipient_email], msg.as_string())
        log.info("Sent email to {0}".format(recipient_email))

    except smtplib.SMTPException, e:
        msg = '%r' % e
        log.exception(msg)
        raise MailerException(msg)
Example #11
0
def encode_string(name, value, maxlinelen=None):
    try:
        header = Header(value.encode("ascii"), "ascii", maxlinelen,
                        header_name=name)
    except UnicodeEncodeError:
        header = Header(value.encode("utf-8"), "utf-8", header_name=name)

    return header.encode(splitchars=' ;,')
 def test_japanese_codecs(self):
     eq = self.ndiffAssertEqual
     j = Charset('euc-jp')
     g = Charset('iso-8859-1')
     h = Header('Hello World!')
     jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa'
     ghello = 'Gr\xfc\xdf Gott!'
     h.append(jhello, j)
     h.append(ghello, g)
     eq(h.encode(), 'Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?=\n =?iso-8859-1?q?Gr=FC=DF?= =?iso-8859-1?q?_Gott!?=')
     eq(decode_header(h.encode()), [('Hello World!', None), ('\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'), ('Gr\xfc\xdf Gott!', 'iso-8859-1')])
     long = 'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9'
     h = Header(long, j, header_name='Subject')
     enc = h.encode()
     eq(enc, '=?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYSE8JWskTztKGyhC?=\n =?iso-2022-jp?b?GyRCMnE8VCROPjVHJyRyQlQkQyRGJCQkXiQ5GyhC?=')
     eq(h.__unicode__().encode('euc-jp'), long)
     return None
Example #13
0
def encode_address(address, encoding):
    parts = re.split("<|>", address.replace('"', ""))
    name = parts[0]

    if len(parts) > 1:
        name = Header(name.encode(encoding.lower()), encoding.upper()).encode()
        name += " <" + parts[1] + ">"

    return name
Example #14
0
 def encode_header(self, value):
     """
     Encode an HTTP header value. Try first natively in ISO-8859-1, then
     UTF-8 encoded quoted string.
     """
     try:
         return smart_unicode(value).encode('iso-8859-1')
     except UnicodeEncodeError:
         header = Header(smart_unicode(value), 'utf-8')
         return header.encode()
Example #15
0
def test_unicode_addresses(mailer):
    msg = mailer.mail(
        subject="subject",
        sender=u'ÄÜÖ → ✓ <*****@*****.**>',
        recipients=[u"Ä <*****@*****.**>", u"Ü <*****@*****.**>"],
        cc=[u"Ö <*****@*****.**>"])
    msg_as_string = str(msg)
    a1 = sanitize_address(u"Ä <*****@*****.**>")
    a2 = sanitize_address(u"Ü <*****@*****.**>")
    h1_a = Header("To: %s, %s" % (a1, a2))
    h1_b = Header("To: %s, %s" % (a2, a1))
    h2 = Header("From: %s" % sanitize_address(u"ÄÜÖ → ✓ <*****@*****.**>"))
    h3 = Header("Cc: %s" % sanitize_address(u"Ö <*****@*****.**>"))
    try:
        assert h1_a.encode() in msg_as_string
    except AssertionError:
        assert h1_b.encode() in msg_as_string
    assert h2.encode() in msg_as_string
    assert h3.encode() in msg_as_string
    def test_japanese_codecs(self):
        if due_to_ironpython_bug("http://tkbgitvstfat01:8080/WorkItemTracking/WorkItem.aspx?artifactMoniker=360541"):
            return
        eq = self.ndiffAssertEqual
        j = Charset("euc-jp")
        g = Charset("iso-8859-1")
        h = Header("Hello World!")
        jhello = "\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa"
        ghello = "Gr\xfc\xdf Gott!"
        h.append(jhello, j)
        h.append(ghello, g)
        # BAW: This used to -- and maybe should -- fold the two iso-8859-1
        # chunks into a single encoded word.  However it doesn't violate the
        # standard to have them as two encoded chunks and maybe it's
        # reasonable <wink> for each .append() call to result in a separate
        # encoded word.
        eq(
            h.encode(),
            """\
Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?=
 =?iso-8859-1?q?Gr=FC=DF?= =?iso-8859-1?q?_Gott!?=""",
        )
        eq(
            decode_header(h.encode()),
            [
                ("Hello World!", None),
                ("\x1b$B%O%m!<%o!<%k%I!*\x1b(B", "iso-2022-jp"),
                ("Gr\xfc\xdf Gott!", "iso-8859-1"),
            ],
        )
        long = "test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9"
        h = Header(long, j, header_name="Subject")
        # test a very long header
        enc = h.encode()
        # TK: splitting point may differ by codec design and/or Header encoding
        eq(
            enc,
            """\
=?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYSE8JWskTztKGyhC?=
 =?iso-2022-jp?b?GyRCMnE8VCROPjVHJyRyQlQkQyRGJCQkXiQ5GyhC?=""",
        )
        # TK: full decode comparison
        eq(h.__unicode__().encode("euc-jp"), long)
Example #17
0
    def test_reply_to(self):
        msg = Message(subject="testing",
                      recipients=["*****@*****.**"],
                      sender="spammer <*****@*****.**>",
                      reply_to="somebody <*****@*****.**>",
                      body="testing")
        response = msg.as_string()

        h = Header("Reply-To: %s" % sanitize_address('somebody <*****@*****.**>'))
        self.assertIn(h.encode(), str(response))
Example #18
0
def test_reply_to(mailer):
    msg = mailer.mail(
        subject="testing",
        recipients=["*****@*****.**"],
        sender="spammer <*****@*****.**>",
        reply_to="somebody <*****@*****.**>",
        body="testing")
    h = Header(
        "Reply-To: %s" % sanitize_address('somebody <*****@*****.**>'))
    assert h.encode() in str(msg)
    def modify_header(self, *args):
        '''Generate the content for the :mailheader:`Sender` header.

:returns: The *mailbox* of the group (a display-name and an angle-address).
:rtype: str'''
        name = to_unicode_or_bust(self.groupInfo.name)
        h = Header(name, UTF8)
        headerName = h.encode()
        addr = self.listInfo.get_property('mailto')
        retval = formataddr((headerName, addr))
        return retval
Example #20
0
    def test_reply_to(self):
        msg = Message(subject="testing",
                      recipients=["*****@*****.**"],
                      sender="spammer <*****@*****.**>",
                      reply_to="somebody <*****@*****.**>",
                      body="testing")
        response = msg.as_string()

        h = Header("Reply-To: %s" %
                   sanitize_address('somebody <*****@*****.**>'))
        self.assertIn(h.encode(), str(response))
Example #21
0
 def _write_headers(self, msg):
     for h, v in msg.items():
         print("%s:" % h, end=" ", file=self._fp)
         if isinstance(v, Header):
             print(v.encode(maxlinelen=self._maxheaderlen), file=self._fp)
         else:
             # Header's got lots of smarts, so use it.
             header = Header(v, maxlinelen=self._maxheaderlen, header_name=h)
             print(header.encode(), file=self._fp)
     # A blank line always separates headers from body
     print(file=self._fp)
Example #22
0
 def receivedHeader(self, helo, origin, rcpt):
     recv = "from {hello0} [{hello1}] message to {rcpts}; {date}"
     rcpts = ",".join([str(r.dest) for r in rcpt])
     date = utils.format_datetime(datetime.datetime.now())
     hh = Header("Received")
     hh.append(
         recv.format(hello0=helo[0].decode('ascii'),
                     hello1=helo[1].decode('ascii'),
                     rcpts=rcpts,
                     date=date).encode('ascii'))
     return hh.encode().encode('ascii')
Example #23
0
    def enc_addresses(addr_list):
        addr = []

        enc_addr = getaddresses(addr_list)

        for a in enc_addr:
            h = Header()
            h.append(a[0])
            h.append('<' + a[1] + '>')
            addr.append(h.encode())

        return ','.join(addr)
Example #24
0
def _formataddr(mailbox, display_name=None, header_name=None):
    header = Header(header_name=header_name)
    if display_name:
        display_name_no_control_chars = remove_control_chars(display_name)
        header.append(display_name_no_control_chars)
        if _SPECIALS.search(header.encode()):
            header = Header(header_name=header_name)
            header.append('"%s"' % email.utils.quote(display_name_no_control_chars))
        header.append("<%s>" % encode_domain_as_idna(mailbox))
    else:
        header.append(encode_domain_as_idna(mailbox))
    return header
Example #25
0
 def _write_headers(self, msg):
     for h, v in msg.items():
         print('%s:' % h, end=' ', file=self._fp)
         if isinstance(v, Header):
             print(v.encode(maxlinelen=self._maxheaderlen), file=self._fp)
         else:
             # Header's got lots of smarts, so use it.
             header = Header(v, maxlinelen=self._maxheaderlen,
                             header_name=h)
             print(header.encode(), file=self._fp)
     # A blank line always separates headers from body
     print(file=self._fp)
 def test_internationalised_subject4(self):
     path = os.path.join(self.examineDir, "internationalised_subject_complex.pdf")
     header = Header()
     header.append(bytes('£100', 'iso-8859-1'), 'iso-8859-1')
     header.append(bytes(' is != how much ', 'utf-8'), 'utf-8')
     header.append(bytes('I have to spend!', 'iso-8859-15'), 'iso-8859-15')
     self.addHeaders(subject=header.encode())
     error = self.invokeDirectly(outputFile=path, extraParams=['--headers'])
     self.assertTrue(os.path.exists(path))
     self.assertEqual('', error)
     self.assertFalse(self.existsByTimeWarning())
     self.assertFalse(self.existsByTimeOriginal())
Example #27
0
    def test_unicode_headers(self):
        msg = Message(subject="subject",
                      sender=u'ÄÜÖ → ✓ <*****@*****.**>',
                      recipients=[u"Ä <*****@*****.**>", u"Ü <*****@*****.**>"],
                      cc=[u"Ö <*****@*****.**>"])

        response = msg.as_string()
        a1 = sanitize_address(u"Ä <*****@*****.**>")
        a2 = sanitize_address(u"Ü <*****@*****.**>")
        h1_a = Header("To: %s, %s" % (a1, a2))
        h1_b = Header("To: %s, %s" % (a2, a1))
        h2 = Header("From: %s" % sanitize_address(u"ÄÜÖ → ✓ <*****@*****.**>"))
        h3 = Header("Cc: %s" % sanitize_address(u"Ö <*****@*****.**>"))

        # Ugly, but there's no guaranteed order of the recipieints in the header
        try:
            self.assertIn(h1_a.encode(), response)
        except AssertionError:
            self.assertIn(h1_b.encode(), response)

        self.assertIn(h2.encode(), response)
        self.assertIn(h3.encode(), response)
Example #28
0
 def _write_headers(self, msg):
     for h, v in msg.items():
         self.write('%s: ' % h)
         if isinstance(v, Header):
             self.write(v.encode(
                 maxlinelen=self._maxheaderlen, linesep=self._NL)+self._NL)
         else:
             # Header's got lots of smarts, so use it.
             header = Header(v, maxlinelen=self._maxheaderlen,
                             header_name=h)
             self.write(header.encode(linesep=self._NL)+self._NL)
     # A blank line always separates headers from body
     self.write(self._NL)
Example #29
0
 def test_internationalised_subject4(self):
     path = os.path.join(self.examineDir,
                         "internationalised_subject_complex.pdf")
     header = Header()
     header.append(bytes('£100', 'iso-8859-1'), 'iso-8859-1')
     header.append(bytes(' is != how much ', 'utf-8'), 'utf-8')
     header.append(bytes('I have to spend!', 'iso-8859-15'), 'iso-8859-15')
     self.addHeaders(subject=header.encode())
     error = self.invokeDirectly(outputFile=path, extraParams=['--headers'])
     self.assertTrue(os.path.exists(path))
     self.assertEqual('', error)
     self.assertFalse(self.existsByTimeWarning())
     self.assertFalse(self.existsByTimeOriginal())
 def _write_headers(self, msg):
     for h, v in msg.items():
         self.write('%s: ' % h)
         if isinstance(v, Header):
             self.write(v.encode(
                 maxlinelen=self._maxheaderlen, linesep=self._NL)+self._NL)
         else:
             # Header's got lots of smarts, so use it.
             header = Header(v, maxlinelen=self._maxheaderlen,
                             header_name=h)
             self.write(header.encode(linesep=self._NL)+self._NL)
     # A blank line always separates headers from body
     self.write(self._NL)
Example #31
0
    def test_unicode_headers(self):
        msg = Message(subject="subject",
                      sender=u'ÄÜÖ → ✓ <*****@*****.**>',
                      recipients=[u"Ä <*****@*****.**>", u"Ü <*****@*****.**>"],
                      cc=[u"Ö <*****@*****.**>"])

        response = msg.as_string()
        a1 = sanitize_address(u"Ä <*****@*****.**>")
        a2 = sanitize_address(u"Ü <*****@*****.**>")
        h1_a = Header("To: %s, %s" % (a1, a2))
        h1_b = Header("To: %s, %s" % (a2, a1))
        h2 = Header("From: %s" % sanitize_address(u"ÄÜÖ → ✓ <*****@*****.**>"))
        h3 = Header("Cc: %s" % sanitize_address(u"Ö <*****@*****.**>"))

        # Ugly, but there's no guaranteed order of the recipieints in the header
        try:
            self.assertIn(h1_a.encode(), response)
        except AssertionError:
            self.assertIn(h1_b.encode(), response)

        self.assertIn(h2.encode(), response)
        self.assertIn(h3.encode(), response)
Example #32
0
def _formataddr(mailbox, display_name=None, header_name=None):
    header = Header(header_name=header_name)
    if display_name:
        display_name_no_control_chars = remove_control_chars(display_name)
        header.append(display_name_no_control_chars)
        if _SPECIALS.search(header.encode()):
            header = Header(header_name=header_name)
            header.append('"%s"' %
                          email.utils.quote(display_name_no_control_chars))
        header.append("<%s>" % encode_domain_as_idna(mailbox))
    else:
        header.append(encode_domain_as_idna(mailbox))
    return header
Example #33
0
    def test_japanese_codecs(self):
        eq = self.ndiffAssertEqual
        jcode = "euc-jp"
        gcode = "iso-8859-1"
        j = Charset(jcode)
        g = Charset(gcode)
        h = Header("Hello World!")
        jhello = str(b'\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc'
                     b'\xa5\xeb\xa5\xc9\xa1\xaa', jcode)
        ghello = str(b'Gr\xfc\xdf Gott!', gcode)
        h.append(jhello, j)
        h.append(ghello, g)
        # BAW: This used to -- and maybe should -- fold the two iso-8859-1
        # chunks into a single encoded word.  However it doesn't violate the
        # standard to have them as two encoded chunks and maybe it's
        # reasonable <wink> for each .append() call to result in a separate
        # encoded word.
        eq(h.encode(), """\
Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?=
 =?iso-8859-1?q?Gr=FC=DF_Gott!?=""")
        eq(decode_header(h.encode()),
           [(b'Hello World! ', None),
            (b'\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'),
            (b'Gr\xfc\xdf Gott!', gcode)])
        subject_bytes = (b'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5'
            b'\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2'
            b'\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3'
            b'\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9')
        subject = str(subject_bytes, jcode)
        h = Header(subject, j, header_name="Subject")
        # test a very long header
        enc = h.encode()
        # TK: splitting point may differ by codec design and/or Header encoding
        eq(enc , """\
=?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYSE8JWskTztKGyhC?=
 =?iso-2022-jp?b?GyRCMnE8VCROPjVHJyRyQlQkQyRGJCQkXiQ5GyhC?=""")
        # TK: full decode comparison
        eq(str(h).encode(jcode), subject_bytes)
Example #34
0
 def add_header(self, key, value, immediate=False):
     """adds a header to the message. by default, headers will added when re-injecting the message back to postfix
     if you set immediate=True the message source will be replaced immediately. Only set this to true if a header must be
     visible to later plugins (eg. for spamassassin rules), otherwise, leave as False which is faster.
     """
     if immediate:
         # is ignore the right thing to do here?
         value.encode('UTF-8', 'ignore')
         hdr = Header(value, header_name=key, continuation_ws=' ')
         hdrline = "%s: %s\n" % (key, hdr.encode())
         src = hdrline + self.get_source()
         self.set_source(src)
     else:
         self.addheaders[key] = value
Example #35
0
 def add_header(self, key, value, immediate=False):
     """adds a header to the message. by default, headers will added when re-injecting the message back to postfix
     if you set immediate=True the message source will be replaced immediately. Only set this to true if a header must be
     visible to later plugins (eg. for spamassassin rules), otherwise, leave as False which is faster.
     """
     if immediate:
         # is ignore the right thing to do here?
         value.encode('UTF-8', 'ignore')
         hdr = Header(value, header_name=key, continuation_ws=' ')
         hdrline = "%s: %s\n" % (key, hdr.encode())
         src = hdrline + self.get_source()
         self.set_source(src)
     else:
         self.addheaders[key] = value
Example #36
0
    def test_japanese_codecs(self):
        if due_to_ironpython_bug(
                "http://tkbgitvstfat01:8080/WorkItemTracking/WorkItem.aspx?artifactMoniker=360541"
        ):
            return
        eq = self.ndiffAssertEqual
        j = Charset("euc-jp")
        g = Charset("iso-8859-1")
        h = Header("Hello World!")
        jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa'
        ghello = 'Gr\xfc\xdf Gott!'
        h.append(jhello, j)
        h.append(ghello, g)
        # BAW: This used to -- and maybe should -- fold the two iso-8859-1
        # chunks into a single encoded word.  However it doesn't violate the
        # standard to have them as two encoded chunks and maybe it's
        # reasonable <wink> for each .append() call to result in a separate
        # encoded word.
        eq(
            h.encode(), """\
Hello World! =?iso-2022-jp?b?GyRCJU8lbSE8JW8hPCVrJUkhKhsoQg==?=
 =?iso-8859-1?q?Gr=FC=DF?= =?iso-8859-1?q?_Gott!?=""")
        eq(decode_header(h.encode()),
           [('Hello World!', None),
            ('\x1b$B%O%m!<%o!<%k%I!*\x1b(B', 'iso-2022-jp'),
            ('Gr\xfc\xdf Gott!', 'iso-8859-1')])
        long = 'test-ja \xa4\xd8\xc5\xea\xb9\xc6\xa4\xb5\xa4\xec\xa4\xbf\xa5\xe1\xa1\xbc\xa5\xeb\xa4\xcf\xbb\xca\xb2\xf1\xbc\xd4\xa4\xce\xbe\xb5\xc7\xa7\xa4\xf2\xc2\xd4\xa4\xc3\xa4\xc6\xa4\xa4\xa4\xde\xa4\xb9'
        h = Header(long, j, header_name="Subject")
        # test a very long header
        enc = h.encode()
        # TK: splitting point may differ by codec design and/or Header encoding
        eq(
            enc, """\
=?iso-2022-jp?b?dGVzdC1qYSAbJEIkWEVqOUYkNSRsJD8lYSE8JWskTztKGyhC?=
 =?iso-2022-jp?b?GyRCMnE8VCROPjVHJyRyQlQkQyRGJCQkXiQ5GyhC?=""")
        # TK: full decode comparison
        eq(h.__unicode__().encode('euc-jp'), long)
Example #37
0
def buildmsgsource(suspect):
    """Build the message source with fuglu headers prepended"""
    # we must prepend headers manually as we can't set a header order in email
    # objects
    origmsgtxt = suspect.get_source()
    newheaders = ""

    for key in suspect.addheaders:
        # is ignore the right thing to do here?
        val = suspect.addheaders[key]
        val.encode('UTF-8', 'ignore')
        #self.logger.debug('Adding header %s : %s'%(key,val))
        hdr = Header(val, header_name=key, continuation_ws=' ')
        newheaders += "%s: %s\n" % (key, hdr.encode())

    modifiedtext = newheaders + origmsgtxt
    return modifiedtext
Example #38
0
def buildmsgsource(suspect):
    """Build the message source with fuglu headers prepended"""
    # we must prepend headers manually as we can't set a header order in email
    # objects
    origmsgtxt = suspect.get_source()
    newheaders = ""

    for key in suspect.addheaders:
        # is ignore the right thing to do here?
        val = suspect.addheaders[key]
        val.encode('UTF-8', 'ignore')
        #self.logger.debug('Adding header %s : %s'%(key,val))
        hdr = Header(val, header_name=key, continuation_ws=' ')
        newheaders += "%s: %s\n" % (key, hdr.encode())

    modifiedtext = newheaders + origmsgtxt
    return modifiedtext
Example #39
0
File: mail.py Project: alkadis/vcv
def to_mail(to_name,
            to_email,
            subject,
            body,
            headers={},
            decorate_body=True,
            email_from=None,
            reply_to=None,
            name_from=None):
    try:
        if email_from is None:
            email_from = config.get('adhocracy.email.from')
        if name_from is None:
            name_from = config.get('adhocracy.site.name')

        if decorate_body:
            body = (
                _(u"Hi %s,") % to_name + u"\r\n\r\n%s\r\n\r\n" % body +
                _(u"Cheers,\r\n\r\n"
                  u"    the %s Team\r\n") % config.get('adhocracy.site.name'))

        # wrap body, but leave long words (e.g. links) intact
        body = u'\n'.join(
            textwrap.fill(line, break_long_words=False, break_on_hyphens=False)
            for line in body.split(u'\n'))

        msg = MIMEText(body.encode(ENCODING), 'plain', ENCODING)

        for k, v in headers.items():
            msg[k] = v

        subject = Header(subject.encode(ENCODING), ENCODING)
        msg['Subject'] = subject
        msg['From'] = _("%s <%s>") % (name_from, email_from)
        to = Header(u"%s <%s>" % (to_name, to_email), ENCODING)
        msg['To'] = to
        if reply_to is not None:
            msg['Reply-To'] = reply_to
        msg['']
        msg['Date'] = email.Utils.formatdate(time())
        msg['X-Mailer'] = "Adhocracy SMTP %s" % version.get_version()
        # log.debug("MAIL\r\n" + msg.as_string())
        send(email_from, to_email, msg.as_string())
    except Exception:
        log.exception("Sending mail failed.")
Example #40
0
def _mail_recipient(recipient_name,
                    recipient_email,
                    sender_name,
                    sender_url,
                    subject,
                    body,
                    headers={}):
    mail_from = config.get('smtp.mail_from')
    msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
    for k, v in headers.items():
        if k in msg.keys():
            msg.replace_header(k, v)
        else:
            msg.add_header(k, v)
    subject = Header(subject.encode('utf-8'), 'utf-8')
    msg['Subject'] = subject
    msg['From'] = _("%s <%s>") % (sender_name, mail_from)
    recipient = u"%s <%s>" % (recipient_name, recipient_email)
    msg['To'] = Header(recipient, 'utf-8')
    msg['Date'] = Utils.formatdate(time())
    msg['X-Mailer'] = "CKAN %s" % ckan.__version__

    # Send the email using Python's smtplib.
    smtp_connection = smtplib.SMTP()
    if 'smtp.test_server' in config:
        # If 'smtp.test_server' is configured we assume we're running tests,
        # and don't use the smtp.server, starttls, user, password etc. options.
        smtp_server = config['smtp.test_server']
        smtp_starttls = False
        smtp_user = None
        smtp_password = None
    else:
        smtp_server = config.get('smtp.server', 'localhost')
        smtp_starttls = paste.deploy.converters.asbool(
            config.get('smtp.starttls'))
        smtp_user = config.get('smtp.user')
        smtp_password = config.get('smtp.password')

    try:
        smtp_connection.connect(smtp_server)
    except socket.error, e:
        log.exception(e)
        raise MailerException(
            'SMTP server could not be connected to: "%s" %s' %
            (smtp_server, e))
    def fromAddr(siteInfo):
        '''Get the formatted ``From`` address for a given site

:param siteInfo: The site for which the From address will be created.
:type siteInfo: :class:`Products.GSContent.interfaces.IGSSiteInfo`
:returns: A formatted email address consisting of the site-name and the
          support email address:
          ``Example Groups Support <*****@*****.**>``.
:rtype: str
'''
        siteName = _('notify-anonymous-support-name', '${siteName} Support',
                     mapping={'siteName': siteInfo.name})
        translatedSiteName = translate(siteName)
        headerName = Header(translatedSiteName, UTF8)
        encodedName = headerName.encode()
        addr = siteInfo.get_support_email()
        retval = formataddr((encodedName, addr))
        return retval
Example #42
0
    def fromAddr(siteInfo):
        '''Get the formatted ``From`` address for a given site

:param siteInfo: The site for which the From address will be created.
:type siteInfo: :class:`Products.GSContent.interfaces.IGSSiteInfo`
:returns: A formatted email address consisting of the site-name and the
          support email address:
          ``Example Groups Support <*****@*****.**>``.
:rtype: str
'''
        siteName = _('notify-anonymous-support-name',
                     '${siteName} Support',
                     mapping={'siteName': siteInfo.name})
        translatedSiteName = translate(siteName)
        headerName = Header(translatedSiteName, UTF8)
        encodedName = headerName.encode()
        addr = siteInfo.get_support_email()
        retval = formataddr((encodedName, addr))
        return retval
    def modify_headers(self, email):
        '''Set the headers in an email message to the "correct" values

:param email: The email message to modify.
:type email: :class:`email.message.Message`
:returns: The modified email message.
:rtype: :class:`email.message.Message`

The :meth:`HeaderModifier.modify_headers` method acquires the
header-adaptors (which conform to the
:class:`.interfaces.IEmailHeaderModifier` interface). It then itterates
through the adaptors (one per header) and then modifies the :obj:`email`
based on the output of the header-adaptor:

``None``:
    The header is deleted.
``str``:
    The header is set to the string.
``unicode``:
    The output is encoded (using :class:`email.header.Header`) and the
    header is set to the string.
'''
        gsm = getGlobalSiteManager()
        for name, adaptor in gsm.getAdapters((self.group, self.request),
                                             IEmailHeaderModifier):
            nv = adaptor.modify_header(email)
            if nv is None:
                # From the email.message docs:
                #   No exception is raised if the named field isn't present
                #   in the headers.
                del(email[name])
            else:
                if type(nv) == bytes:  # == str in Python 2
                    newValue = nv
                else:  # Unicode
                    hv = Header(nv, 'utf-8')
                    newValue = hv.encode()
                if name in email:
                    email.replace_header(name, newValue)
                else:
                    email.add_header(name, newValue)
        return email
Example #44
0
    def attach_csv(self, source, filename):
        if not self._msg:
            return

        ctype = 'application/octet-stream'

        maintype, subtype = ctype.split('/', 1)
        base = MIMEBase(maintype, subtype)
        with open('%s/%s' % (source, filename), 'rb') as fp:
            base.set_payload(fp.read())
        encoders.encode_base64(base)

        header = Header(filename, charset=default_unicode)
        base.add_header('Content-Disposition',
                        'attachment',
                        filename='%s' % header.encode())

        self._msg.attach(base)

        fp.close()
Example #45
0
def generate_relay_From(original_from_address):
    relay_display_name, relay_from_address = parseaddr(
        settings.RELAY_FROM_ADDRESS)
    # RFC 2822 (https://tools.ietf.org/html/rfc2822#section-2.1.1)
    # says email header lines must not be more than 998 chars long.
    # Encoding display names to longer than 998 chars will add wrap
    # characters which are unsafe. (See https://bugs.python.org/issue39073)
    # So, truncate the original sender to 900 chars so we can add our
    # "[via Relay] <relayfrom>" and encode it all.
    if len(original_from_address) > 998:
        original_from_address = '%s ...' % original_from_address[:900]
    # line breaks in From: will encode to unsafe chars, so strip them.
    original_from_address = (original_from_address.replace(
        '\u2028', '').replace('\r', '').replace('\n', ''))

    display_name = Header('"%s [via Relay]"' % (original_from_address),
                          'UTF-8')
    formatted_from_address = str(
        Address(display_name.encode(maxlinelen=998),
                addr_spec=relay_from_address))
    return formatted_from_address
Example #46
0
def mail_recipient(recipient_name, recipient_email,
        subject, body, headers={}):
    mail_from = config.get('openspending.mail_from', '*****@*****.**')
    body = add_msg_niceties(recipient_name, body, app_globals.site_title)
    msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
    for k, v in headers.items(): msg[k] = v
    subject = Header(subject.encode('utf-8'), 'utf-8')
    msg['Subject'] = subject
    msg['From'] = _("%s <%s>") % (app_globals.site_title, mail_from)
    recipient = u"%s <%s>" % (recipient_name, recipient_email)
    msg['To'] = Header(recipient, 'utf-8')
    msg['Date'] = Utils.formatdate(time())
    msg['X-Mailer'] = "OpenSpending"
    try:
        server = smtplib.SMTP(config.get('smtp_server', 'localhost'))
        server.sendmail(mail_from, [recipient_email], msg.as_string())
        server.quit()
    except Exception, e:
        msg = '%r' % e
        log.exception(msg)
        raise MailerException(msg)
Example #47
0
def forbid_multi_line_headers(name, val, encoding):
    """Forbids multi-line headers, to prevent header injection."""
    encoding = encoding or 'utf-8'
    val = force_unicode(val, encoding)
    if '\n' in val or '\r' in val:
        raise BadHeaderError("Header values can't contain newlines (got %r for header %r)" % (val, name))
    try:
        val = val.encode('ascii')
    except UnicodeEncodeError:
        if name.lower() in ('to', 'from', 'cc'):
            result = []
            for nm, addr in getaddresses((val,)):
                nm = str(Header(nm.encode(encoding), encoding))
                result.append(formataddr((nm, str(addr))))
            val = ', '.join(result)
        else:
            val = Header(val.encode(encoding), encoding)
    else:
        if name.lower() == 'subject':
            val = Header(val)
    return name, val
Example #48
0
def buildmsgsource(suspect):
    """Build the message source with fuglu headers prepended"""

    # we must prepend headers manually as we can't set a header order in email
    # objects

    # -> the original message source is bytes
    origmsgtxt = suspect.get_source()
    newheaders = ""

    for key in suspect.addheaders:
        # is ignore the right thing to do here?
        val = suspect.addheaders[key]
        #self.logger.debug('Adding header %s : %s'%(key,val))
        hdr = Header(val, header_name=key, continuation_ws=' ')
        newheaders += "%s: %s\r\n" % (key, hdr.encode())

    # the original message should be in bytes, make sure the header added
    # is an encoded string as well
    modifiedtext = force_bString(newheaders) + force_bString(origmsgtxt)
    return modifiedtext
Example #49
0
def send_test(subject, document, filename, html, **kw):
    if subject:
        msg = MIMEMultipart()
        msg['Subject'] = subject
        msg['From'] = kw.get('addr_from')
        msg['To'] = kw.get('addr_to')

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

        if isinstance(document, bytes):
            fp = io.BytesIO(document)
        else:
            fp = io.BytesIO()
            document.save(fp)

        ctype = kw.get(
            'ctype'
        ) or 'application/msword'  #octet-stream vnd.ms-excel application/pdf vnd.ms-powerpoint image/png

        maintype, subtype = ctype.split('/', 1)
        base = MIMEBase(maintype, subtype)
        fp.seek(0)
        base.set_payload(fp.read())
        encoders.encode_base64(base)

        header = Header(filename, charset=default_unicode)
        base.add_header('Content-Disposition',
                        'attachment',
                        filename='%s' % header.encode())

        msg.attach(base)

        smtp = smtplib.SMTP(smtphost['host'], smtphost['port'])
        smtp.send_message(msg)
        smtp.quit()

        fp.close()

    return 1
Example #50
0
def mail_recipient(recipient_name, recipient_email, subject, body, headers={}):
    mail_from = config.get('openspending.mail_from',
                           '*****@*****.**')
    body = add_msg_niceties(recipient_name, body, app_globals.site_title)
    msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
    for k, v in headers.items():
        msg[k] = v
    subject = Header(subject.encode('utf-8'), 'utf-8')
    msg['Subject'] = subject
    msg['From'] = _("%s <%s>") % (app_globals.site_title, mail_from)
    recipient = u"%s <%s>" % (recipient_name, recipient_email)
    msg['To'] = Header(recipient, 'utf-8')
    msg['Date'] = Utils.formatdate(time())
    msg['X-Mailer'] = "OpenSpending"
    try:
        server = smtplib.SMTP(config.get('smtp_server', 'localhost'))
        server.sendmail(mail_from, [recipient_email], msg.as_string())
        server.quit()
    except Exception, e:
        msg = '%r' % e
        log.exception(msg)
        raise MailerException(msg)
 def _write_headers(self, msg):
     # This is almost the same as the string version, except for handling
     # strings with 8bit bytes.
     for h, v in msg._headers:
         self.write('%s: ' % h)
         if isinstance(v, Header):
             self.write(v.encode(maxlinelen=self._maxheaderlen)+NL)
         elif _has_surrogates(v):
             # If we have raw 8bit data in a byte string, we have no idea
             # what the encoding is.  There is no safe way to split this
             # string.  If it's ascii-subset, then we could do a normal
             # ascii split, but if it's multibyte then we could break the
             # string.  There's no way to know so the least harm seems to
             # be to not split the string and risk it being too long.
             self.write(v+NL)
         else:
             # Header's got lots of smarts and this string is safe...
             header = Header(v, maxlinelen=self._maxheaderlen,
                             header_name=h)
             self.write(header.encode(linesep=self._NL)+self._NL)
     # A blank line always separates headers from body
     self.write(self._NL)
Example #52
0
def encode_header(key, value):
    """
    encodes a unicode string as a valid header value

    :param key: the header field this value will be stored in
    :type key: str
    :param value: the value to be encoded
    :type value: unicode
    """
    # handle list of "realname <email>" entries separately
    if key.lower() in ['from', 'to', 'cc', 'bcc']:
        rawentries = email.utils.getaddresses([value])
        encodedentries = []
        for name, address in rawentries:
            # try to encode as ascii, if that fails, revert to utf-8
            # name must be a unicode string here
            namepart = Header(name)
            # append address part encoded as ascii
            entry = email.utils.formataddr((namepart.encode(), address))
            encodedentries.append(entry)
        value = Header(', '.join(encodedentries))
    else:
        value = Header(value)
    return value
Example #53
0
    def send_raw(self, job, message, config):
        config = dict(self.middleware.call_sync('mail.config'), **config)

        if config['fromname']:
            from_addr = Header(config['fromname'], 'utf-8')
            try:
                config['fromemail'].encode('ascii')
            except UnicodeEncodeError:
                from_addr.append(f'<{config["fromemail"]}>', 'utf-8')
            else:
                from_addr.append(f'<{config["fromemail"]}>', 'ascii')
        else:
            try:
                config['fromemail'].encode('ascii')
            except UnicodeEncodeError:
                from_addr = Header(config['fromemail'], 'utf-8')
            else:
                from_addr = Header(config['fromemail'], 'ascii')

        interval = message.get('interval')
        if interval is None:
            interval = timedelta()
        else:
            interval = timedelta(seconds=interval)

        sw_name = self.middleware.call_sync('system.version').split('-', 1)[0]

        channel = message.get('channel')
        if not channel:
            channel = sw_name.lower()
        if interval > timedelta():
            channelfile = '/tmp/.msg.%s' % (channel)
            last_update = datetime.now() - interval
            try:
                last_update = datetime.fromtimestamp(
                    os.stat(channelfile).st_mtime)
            except OSError:
                pass
            timediff = datetime.now() - last_update
            if (timediff >= interval) or (timediff < timedelta()):
                # Make sure mtime is modified
                # We could use os.utime but this is simpler!
                with open(channelfile, 'w') as f:
                    f.write('!')
            else:
                raise CallError(
                    'This message was already sent in the given interval')

        verrors = self.__password_verify(config['pass'], 'mail-config.pass')
        if verrors:
            raise verrors
        to = message.get('to')
        if not to:
            to = [
                self.middleware.call_sync('user.query',
                                          [('username', '=', 'root')],
                                          {'get': True})['email']
            ]
            if not to[0]:
                raise CallError('Email address for root is not configured')

        if message.get('attachments'):
            job.check_pipe("input")

            def read_json():
                f = job.pipes.input.r
                data = b''
                i = 0
                while True:
                    read = f.read(1048576)  # 1MiB
                    if read == b'':
                        break
                    data += read
                    i += 1
                    if i > 50:
                        raise ValueError(
                            'Attachments bigger than 50MB not allowed yet')
                if data == b'':
                    return None
                return json.loads(data)

            attachments = read_json()
        else:
            attachments = None

        if 'html' in message or attachments:
            msg = MIMEMultipart()
            msg.preamble = 'This is a multi-part message in MIME format.'
            if 'html' in message:
                msg2 = MIMEMultipart('alternative')
                msg2.attach(
                    MIMEText(message['text'], 'plain', _charset='utf-8'))
                msg2.attach(MIMEText(message['html'], 'html',
                                     _charset='utf-8'))
                msg.attach(msg2)
            if attachments:
                for attachment in attachments:
                    m = Message()
                    m.set_payload(attachment['content'])
                    for header in attachment.get('headers'):
                        m.add_header(header['name'], header['value'],
                                     **(header.get('params') or {}))
                    msg.attach(m)
        else:
            msg = MIMEText(message['text'], _charset='utf-8')

        msg['Subject'] = message['subject']

        msg['From'] = from_addr
        msg['To'] = ', '.join(to)
        if message.get('cc'):
            msg['Cc'] = ', '.join(message.get('cc'))
        msg['Date'] = formatdate()

        local_hostname = self.middleware.call_sync('system.hostname')

        msg['Message-ID'] = "<%s-%s.%s@%s>" % (
            sw_name.lower(), datetime.utcnow().strftime("%Y%m%d.%H%M%S.%f"),
            base64.urlsafe_b64encode(os.urandom(3)), local_hostname)

        extra_headers = message.get('extra_headers') or {}
        for key, val in list(extra_headers.items()):
            # We already have "Content-Type: multipart/mixed" and setting "Content-Type: text/plain" like some scripts
            # do will break python e-mail module.
            if key.lower() == "content-type":
                continue

            if key in msg:
                msg.replace_header(key, val)
            else:
                msg[key] = val

        syslog.openlog(logoption=syslog.LOG_PID, facility=syslog.LOG_MAIL)
        try:
            if config['oauth']:
                self.middleware.call_sync('mail.gmail_send', msg, config)
            else:
                server = self._get_smtp_server(config,
                                               message['timeout'],
                                               local_hostname=local_hostname)
                # NOTE: Don't do this.
                #
                # If smtplib.SMTP* tells you to run connect() first, it's because the
                # mailserver it tried connecting to via the outgoing server argument
                # was unreachable and it tried to connect to 'localhost' and barfed.
                # This is because FreeNAS doesn't run a full MTA.
                # else:
                #    server.connect()
                headers = '\n'.join([f'{k}: {v}' for k, v in msg._headers])
                syslog.syslog(f"sending mail to {', '.join(to)}\n{headers}")
                server.sendmail(from_addr.encode(), to, msg.as_string())
                server.quit()
        except Exception as e:
            # Don't spam syslog with these messages. They should only end up in the
            # test-email pane.
            # We are only interested in ValueError, not subclasses.
            if e.__class__ is ValueError:
                raise CallError(str(e))
            syslog.syslog(f'Failed to send email to {", ".join(to)}: {str(e)}')
            if isinstance(e, smtplib.SMTPAuthenticationError):
                raise CallError(
                    f'Authentication error ({e.smtp_code}): {e.smtp_error}',
                    errno.EAUTH if osc.IS_FREEBSD else errno.EPERM)
            self.logger.warn('Failed to send email: %s', str(e), exc_info=True)
            if message['queue']:
                with MailQueue() as mq:
                    mq.append(msg)
            raise CallError(f'Failed to send email: {e}')
        return True
Example #54
0
def generate_relay_From(original_from_address):
    relay_display_name, relay_from_address = parseaddr(
        settings.RELAY_FROM_ADDRESS)
    display_name = Header(
        '"' + quote('%s [via Relay]' % (original_from_address)) + '"', 'UTF-8')
    return relay_from_address, display_name.encode()
Example #55
0
    def create(self):
        """
        Create an auto response object from whole cloth.

        The auto response is a MIME compliant entity with either one
        or two bodyparts, depending on what
        Defaults.AUTORESPONSE_INCLUDE_SENDER_COPY is set to.

        In most cases, the object will look like:

        multipart/mixed
                text/plain (response text)
                message/rfc822 or text/rfc822-headers (sender's message)
        """
        # Headers that users shouldn't be setting in their templates.
        bad_headers = ['MIME-Version', 'Content-Type', 'BodyCharset',
                       'Content-Transfer-Encoding', 'Content-Disposition',
                       'Content-Description']
        for h in bad_headers:
            if self.bouncemsg.has_key(h):
                del self.bouncemsg[h]
        textpart = MIMEText(self.bouncemsg.get_payload(), 'plain',
                            self.bodycharset)
        bodyparts = 1 + Defaults.AUTORESPONSE_INCLUDE_SENDER_COPY
        if bodyparts == 1:
            # A single text/plain entity.
            self.mimemsg = textpart
        elif bodyparts > 1:
            # A multipart/mixed entity with two bodyparts.
            self.mimemsg = MIMEMultipart('mixed')
            if self.responsetype == 'request':
                textpart['Content-Description'] = 'Confirmation Request'
            elif self.responsetype == 'accept':
                textpart['Content-Description'] = 'Confirmation Acceptance'
            elif self.responsetype == 'bounce':
                textpart['Content-Description'] = 'Failure Notice'
            textpart['Content-Disposition'] = 'inline'
            self.mimemsg.attach(textpart)
            if Defaults.AUTORESPONSE_INCLUDE_SENDER_COPY == 1:
                # include the headers only as a text/rfc822-headers part.
                rfc822part = MIMEText(
                    self.msgin_as_string[:self.msgin_as_string.index('\n\n')+1],
                    'rfc822-headers', self.msgin.get_charsets(DEFAULT_CHARSET)[0])
                rfc822part['Content-Description'] = 'Original Message Headers'
            elif Defaults.AUTORESPONSE_INCLUDE_SENDER_COPY == 2:
                # include the entire message as a message/rfc822 part.
                # If the message was > CONFIRM_MAX_MESSAGE_SIZE, it has already
                # been truncated appropriately in the constructor.
                rfc822part = MIMEMessage(self.msgin)
                rfc822part['Content-Description'] = 'Original Message'
            rfc822part['Content-Disposition'] = 'inline'
            self.mimemsg.attach(rfc822part)
        # RFC 2183 section 2.10 permits the use Content-Disposition in
        # the main body of the message.
        self.mimemsg['Content-Disposition'] = 'inline'
        # fold the template headers into the main entity.
        for k, v in self.bouncemsg.items():
            ksplit = k.split('.', 1)
            if len(ksplit) == 1:
                hdrcharset = DEFAULT_CHARSET
            else:
                # Header.CHARSET: Value
                k = ksplit[0]
                hdrcharset = ksplit[1]
            # headers like `From:' which contain e-mail addresses
            # might need the "Fullname" portion encoded, but the
            # address portion must never be encoded.
            if k.lower() in map(lambda s: s.lower(),
                                Defaults.TEMPLATE_EMAIL_HEADERS):
                name, addr = parseaddr(v)
                if name and hdrcharset.lower() not in ('ascii', 'us-ascii'):
                    h = Header(name, hdrcharset, errors='replace')
                    name = h.encode()
                self.mimemsg[k] = formataddr((name, addr))
            # headers like `Subject:' might contain an encoded string,
            # so we need to decode that first before encoding the
            # entire header value.
            elif hdrcharset.lower() not in ('ascii', 'us-ascii') and \
                     k.lower() in map(lambda s: s.lower(),
                                      Defaults.TEMPLATE_ENCODED_HEADERS):
                h = Header(charset=hdrcharset, header_name=k, errors='replace')
                decoded_seq = decode_header(v)
                for s, charset in decoded_seq:
                    h.append(s, charset)
                self.mimemsg[k] = h
            else:
                self.mimemsg[k] = Header(v, hdrcharset, header_name=k,
                                         errors='replace')
        # Add some new headers to the main entity.
        timesecs = time.time()
        self.mimemsg['Date'] = Util.make_date(timesecs) # required by RFC 2822
        self.mimemsg['Message-ID'] = Util.make_msgid(timesecs) # Ditto
        # References
        refs = []
        for h in ['references', 'message-id']:
            if self.msgin.has_key(h):
                refs = refs + self.msgin.get(h).split()
        if refs:
            self.mimemsg['References'] = '\n\t'.join(refs)
        # In-Reply-To
        if self.msgin.has_key('message-id'):
            self.mimemsg['In-Reply-To'] =  self.msgin.get('message-id')
        self.mimemsg['To'] = self.recipient
        # Some auto responders respect this header.
        self.mimemsg['Precedence'] = 'bulk'
        # Auto-Submitted per draft-moore-auto-email-response-00.txt
        if self.responsetype in ('request', 'accept'):
            self.mimemsg['Auto-Submitted'] = 'auto-replied'
        elif self.responsetype == 'bounce':
            self.mimemsg['Auto-Submitted'] = 'auto-generated (failure)'
        self.mimemsg['X-Delivery-Agent'] = 'TMDA/%s (%s)' % (Version.TMDA,
                                                             Version.CODENAME)
        # Optionally, add some custom headers.
        Util.add_headers(self.mimemsg, Defaults.ADDED_HEADERS_SERVER)
        # Optionally, remove some headers.
        Util.purge_headers(self.mimemsg, Defaults.PURGED_HEADERS_SERVER)
Example #56
0
def _mail_recipient_html(sender_name='Humanitarian Data Exchange (HDX)',
                         sender_email='*****@*****.**',
                         recipients_list=None,
                         subject=None,
                         content_dict=None,
                         cc_recipients_list=None,
                         bcc_recipients_list=None,
                         footer=True,
                         headers={},
                         reply_wanted=False,
                         snippet='email/email.html',
                         file=None):

    if sender_email:
        mail_from = sender_email
    else:
        mail_from = config.get(
            'hdx_smtp.mail_from_please_reply') if reply_wanted else config.get(
                'smtp.mail_from')

    template_data = {
        'data': {
            'data': content_dict,
            'footer': footer,
            '_snippet': snippet
        },
    }
    body_html = mailer.render_jinja2('email/email.html', template_data)

    # msg = MIMEMultipart('alternative')
    msg = MIMEMultipart()
    for k, v in headers.items():
        msg[k] = v
    subject = Header(subject.encode('utf-8'), 'utf-8')
    msg['Subject'] = subject
    msg['From'] = _(u"%s <%s>") % (sender_name, mail_from)
    recipient_email_list = []
    recipients = None
    if recipients_list:
        for r in recipients_list:
            email = r.get('email')
            recipient_email_list.append(email)
            display_name = r.get('display_name')
            if display_name:
                recipient = u"%s <%s>" % (display_name, email)
            else:
                recipient = u"%s" % email
            # else:
            # no recipient list provided
            recipients = ', '.join([recipients, recipient
                                    ]) if recipients else recipient

    msg['To'] = Header(recipients, 'utf-8')
    if bcc_recipients_list:
        for r in bcc_recipients_list:
            recipient_email_list.append(r.get('email'))
    cc_recipients = None
    if cc_recipients_list:
        for r in cc_recipients_list:
            recipient_email_list.append(r.get('email'))
            cc_recipient = u"%s <%s>" % (r.get('display_name'), r.get('email'))
            cc_recipients = ', '.join([cc_recipients, cc_recipient
                                       ]) if cc_recipients else cc_recipient
        msg['Cc'] = cc_recipients if cc_recipients else ''

    msg['Date'] = Utils.formatdate(time())
    msg['X-Mailer'] = "CKAN %s" % ckan.__version__
    if sender_email:
        msg['Reply-To'] = Header((u"%s <%s>" % (sender_name, sender_email)),
                                 'utf-8')
    part = MIMEText(body_html, 'html', 'utf-8')
    msg.attach(part)

    if isinstance(file, cgi.FieldStorage):
        _part = MIMEBase('application', 'octet-stream')
        _part.set_payload(file.file.read())
        Encoders.encode_base64(_part)
        extension = file.filename.split('.')[-1]
        header_value = 'attachment; filename=attachment.{0}'.format(extension)
        _part.add_header('Content-Disposition', header_value)
        msg.attach(_part)

    # Send the email using Python's smtplib.
    smtp_connection = smtplib.SMTP()
    if 'smtp.test_server' in config:
        # If 'smtp.test_server' is configured we assume we're running tests,
        # and don't use the smtp.server, starttls, user, password etc. options.
        smtp_server = config['smtp.test_server']
        smtp_starttls = False
        smtp_user = None
        smtp_password = None
    else:
        smtp_server = config.get('smtp.server', 'localhost')
        smtp_starttls = paste.deploy.converters.asbool(
            config.get('smtp.starttls'))
        smtp_user = config.get('smtp.user')
        smtp_password = config.get('smtp.password')
    smtp_connection.connect(smtp_server)
    try:
        # smtp_connection.set_debuglevel(True)

        # Identify ourselves and prompt the server for supported features.
        smtp_connection.ehlo()

        # If 'smtp.starttls' is on in CKAN config, try to put the SMTP
        # connection into TLS mode.
        if smtp_starttls:
            if smtp_connection.has_extn('STARTTLS'):
                smtp_connection.starttls()
                # Re-identify ourselves over TLS connection.
                smtp_connection.ehlo()
            else:
                raise MailerException("SMTP server does not support STARTTLS")

        # If 'smtp.user' is in CKAN config, try to login to SMTP server.
        if smtp_user:
            assert smtp_password, ("If smtp.user is configured then "
                                   "smtp.password must be configured as well.")
            smtp_connection.login(smtp_user, smtp_password)

        smtp_connection.sendmail(mail_from, recipient_email_list,
                                 msg.as_string())
        log.info("Sent email to provided list of recipients")

    except smtplib.SMTPException, e:
        msg = '%r' % e
        log.exception(msg)
        raise MailerException(msg)
Example #57
0
 def encode(self, splitchars=' ', **kwargs):  # only split on spaces, rather than splitchars=';, '
     return Header.encode(self, splitchars, **kwargs)
Example #58
0
    def render_POST(self, request):
        send_cors(request)
        err, args = get_args(request, ("medium", "address", "room_id", "sender",))
        if err:
            return json.dumps(err)
        medium = args["medium"]
        address = args["address"]
        roomId = args["room_id"]
        sender = args["sender"]

        globalAssocStore = GlobalAssociationStore(self.sydent)
        mxid = globalAssocStore.getMxid(medium, address)
        if mxid:
            request.setResponseCode(400)
            return json.dumps({
                "errcode": "THREEPID_IN_USE",
                "error": "Binding already known",
                "mxid": mxid,
            })

        if medium != "email":
            request.setResponseCode(400)
            return json.dumps({
                "errcode": "M_UNRECOGNIZED",
                "error": "Didn't understand medium '%s'" % (medium,),
            })

        token = self._randomString(128)

        tokenStore = JoinTokenStore(self.sydent)

        ephemeralPrivateKey = nacl.signing.SigningKey.generate()
        ephemeralPublicKey = ephemeralPrivateKey.verify_key

        ephemeralPrivateKeyBase64 = encode_base64(ephemeralPrivateKey.encode(), True)
        ephemeralPublicKeyBase64 = encode_base64(ephemeralPublicKey.encode(), True)

        tokenStore.storeEphemeralPublicKey(ephemeralPublicKeyBase64)
        tokenStore.storeToken(medium, address, roomId, sender, token)

        substitutions = {}
        for key, values in request.args.items():
            if len(values) == 1 and type(values[0]) == str:
                substitutions[key] = values[0]
        substitutions["token"] = token

        required = [
            'sender_display_name',
            'token',
            'room_name',
            'bracketed_room_name',
            'room_avatar_url',
            'sender_display_name',
            'guest_user_id',
            'guest_access_token',
        ]
        for k in required:
            substitutions.setdefault(k, '')

        substitutions["ephemeral_private_key"] = ephemeralPrivateKeyBase64
        if substitutions["room_name"] != '':
            substitutions["bracketed_room_name"] = "(%s)" % substitutions["room_name"]

        subject_header = Header(self.sydent.cfg.get('email', 'email.invite.subject', raw=True) % substitutions, 'utf8')
        substitutions["subject_header_value"] = subject_header.encode()

        sendEmail(self.sydent, "email.invite_template", address, substitutions)

        pubKey = self.sydent.keyring.ed25519.verify_key
        pubKeyBase64 = encode_base64(pubKey.encode())

        baseUrl = "%s/_matrix/identity/api/v1" % (self.sydent.cfg.get('http', 'client_http_base'),)

        keysToReturn = []
        keysToReturn.append({
            "public_key": pubKeyBase64,
            "key_validity_url": baseUrl + "/pubkey/isvalid",
        })
        keysToReturn.append({
            "public_key": ephemeralPublicKeyBase64,
            "key_validity_url": baseUrl + "/pubkey/ephemeral/isvalid",
        })

        resp = {
            "token": token,
            "public_key": pubKeyBase64,
            "public_keys": keysToReturn,
            "display_name": self.redact(address),
        }

        return json.dumps(resp)
Example #59
0
 def enc_addr_header(name, email):
     header = Header(name)
     header.append(email)
     return header.encode()
Example #60
0
def _mail_recipient(recipient_name,
                    recipient_email,
                    sender_name,
                    sender_url,
                    subject,
                    body,
                    headers={}):
    mail_from = config.get('smtp.mail_from')
    body = add_msg_niceties(recipient_name, body, sender_name, sender_url)
    msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')
    for k, v in headers.items():
        msg[k] = v
    subject = Header(subject.encode('utf-8'), 'utf-8')
    msg['Subject'] = subject
    msg['From'] = _("%s <%s>") % (sender_name, mail_from)
    recipient = u"%s <%s>" % (recipient_name, recipient_email)
    msg['To'] = Header(recipient, 'utf-8')
    msg['Date'] = Utils.formatdate(time())
    msg['X-Mailer'] = "CKAN %s" % ckan.__version__

    # Send the email using Python's smtplib.
    smtp_connection = smtplib.SMTP()
    if 'smtp.test_server' in config:
        # If 'smtp.test_server' is configured we assume we're running tests,
        # and don't use the smtp.server, starttls, user, password etc. options.
        smtp_server = config['smtp.test_server']
        smtp_starttls = False
        smtp_user = None
        smtp_password = None
    else:
        smtp_server = config.get('smtp.server', 'localhost')
        smtp_starttls = paste.deploy.converters.asbool(
            config.get('smtp.starttls'))
        smtp_user = config.get('smtp.user')
        smtp_password = config.get('smtp.password')
    smtp_connection.connect(smtp_server)
    try:
        #smtp_connection.set_debuglevel(True)

        # Identify ourselves and prompt the server for supported features.
        smtp_connection.ehlo()

        # If 'smtp.starttls' is on in CKAN config, try to put the SMTP
        # connection into TLS mode.
        if smtp_starttls:
            if smtp_connection.has_extn('STARTTLS'):
                smtp_connection.starttls()
                # Re-identify ourselves over TLS connection.
                smtp_connection.ehlo()
            else:
                raise MailerException("SMTP server does not support STARTTLS")

        # If 'smtp.user' is in CKAN config, try to login to SMTP server.
        if smtp_user:
            assert smtp_password, ("If smtp.user is configured then "
                                   "smtp.password must be configured as well.")
            smtp_connection.login(smtp_user, smtp_password)

        smtp_connection.sendmail(mail_from, [recipient_email], msg.as_string())
        log.info("Sent email to {0}".format(recipient_email))

    except smtplib.SMTPException, e:
        msg = '%r' % e
        log.exception(msg)
        raise MailerException(msg)