def test_empty_message(self):
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Subject"] = "subject (issue%s)\r\n\r\n" % self.issue.key().id()
     self.assertRaises(
         views.InvalidIncomingEmailError, views._process_incoming_mail, msg.as_string(), "*****@*****.**"
     )
Example #2
0
 def _send_message(self):
     msg = Message()
     msg["From"] = "Dummy Sender <*****@*****.**>"
     msg["Message-ID"] = "<msg>"
     msg["Subject"] = "Dummy message"
     msg.set_payload("Dummy content")
     return add_to_list("*****@*****.**", msg)
Example #3
0
 def test_empty_message(self):
   msg = Message()
   msg['From'] = '*****@*****.**'
   msg['Subject'] = 'subject (issue%s)\r\n\r\n' % self.issue.key.id()
   self.assertRaises(views.InvalidIncomingEmailError,
                     views._process_incoming_mail, msg.as_string(),
                     '*****@*****.**')
Example #4
0
def dump_message(file, headers, props=None, content=None):
    msg = Message()
    for (name, value) in headers:
        msg[name] = value
    payload = BytesIO()
    
    if props is not None:
        start = payload.tell()
        for (key, value) in props.items():
            payload.write("K {}\n".format(len(key)).encode("ascii"))
            payload.writelines((key.encode("ascii"), b"\n"))
            payload.write("V {}\n".format(len(value)).encode("ascii"))
            payload.writelines((value.encode("ascii"), b"\n"))
        payload.write(b"PROPS-END\n")
        
        msg["Prop-content-length"] = format(payload.tell() - start)
    
    if content is not None:
        msg["Text-content-length"] = format(len(content))
        payload.write(content)
    
    if props is not None or content is not None:
        payload = payload.getvalue()
        msg["Content-length"] = format(len(payload))
        
        # Workaround for Python issue 18324, "set_payload does not handle
        # binary payloads correctly", http://bugs.python.org/issue18324
        msg.set_payload(payload.decode("ascii", "surrogateescape"))
    
    BytesGenerator(file, mangle_from_=False).flatten(msg)
Example #5
0
    def _mail_missing_message(self, subject, text):
        # FIXME: This should be handled properly via the event api
        # we should send a missing message on the mq, and let any reporter
        # handle that

        # first, see if we have a MailNotifier we can use. This gives us a
        # fromaddr and a relayhost.
        buildmaster = self.botmaster.master
        for st in buildmaster.services:
            if isinstance(st, MailNotifier):
                break
        else:
            # if not, they get a default MailNotifier, which always uses SMTP
            # to localhost and uses a dummy fromaddr of "buildbot".
            log.msg("worker-missing msg using default MailNotifier")
            st = MailNotifier("buildbot")
        # now construct the mail

        m = Message()
        m.set_payload(text)
        m['Date'] = formatdate(localtime=True)
        m['Subject'] = subject
        m['From'] = st.fromaddr
        recipients = self.notify_on_missing
        m['To'] = ", ".join(recipients)
        d = st.sendMessage(m, recipients)
        # return the Deferred for testing purposes
        return d
 def do_email(self):
     """将最终结果以邮件形式发送"""
     print "准备发送邮件..."
     from_addr = self.conf.get("addr", "from")
     to_addr = self.conf.get("addr", "to")
     cc_addr = self.conf.get("addr", "cc")
     smtpserver = self.conf.get("mail", "smtpserver")
     username = self.conf.get("mail", "username")
     password = self.conf.get("mail", "password")
     to_and_cc_addr = self._str2list(to_addr) + self._str2list(cc_addr)
     if self.do_check_email_conf(smtpserver, username, password, from_addr, to_and_cc_addr) is not True:
         return
     subject = self.program_range + self.program_type + time.strftime("(发送时间:%Y年%m月%d日)", time.localtime())
     message = Message()
     message["Subject"] = subject
     message["From"] = from_addr
     message["To"] = to_addr
     message["Cc"] = cc_addr
     message.set_payload(self.file_content)
     smtp = smtplib.SMTP()
     smtp.connect(smtpserver)
     smtp.login(username, password)  
     smtp.sendmail(from_addr, to_and_cc_addr, message.as_string())
     smtp.quit()
     print "发送完毕,请到邮箱中查看抓取信息..."
Example #7
0
  def test_get_activities_extra_fetches_fail(self):
    """Sometimes the extras fetches return errors. Ignore that."""
    self.init()

    batch = MIMEMultipart()
    for i in range(3):
      msg = Message()
      msg.set_payload('HTTP/1.1 500 Foo Bar\n\r\n\r\n')
      msg['Content-ID'] = '<response-abc+%d>' % (i + 1)
      batch.attach(msg)

    # as_string() must be called before get_boundary() to generate the
    # boundaries between parts, but can't be called again, so we capture the
    # result.
    batch_str = batch.as_string()

    self.auth_entity.http = lambda: http.HttpMockSequence(
      [({'status': '200'}, json.dumps({'items': [ACTIVITY_GP_EXTRAS]})),
       ({'status': '200',
         'content-type': 'multipart/mixed; boundary="%s"' % batch.get_boundary()},
        batch_str),
       ])

    cache = util.CacheDict()
    self.assert_equals([ACTIVITY_AS], self.googleplus.get_activities(
        fetch_replies=True, fetch_likes=True, fetch_shares=True, cache=cache))
    for prefix in 'AGC ', 'AGL ', 'AGS ':
      self.assertNotIn(prefix + '001', cache)
Example #8
0
 def test_payload_encoding_utf8(self):
     jhello = str(b'\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc'
                  b'\xa5\xeb\xa5\xc9\xa1\xaa', 'euc-jp')
     msg = Message()
     msg.set_payload(jhello, 'utf-8')
     ustr = msg.get_payload(decode=True).decode(msg.get_content_charset())
     self.assertEqual(jhello, ustr)
 def test_matches(self):
     from email.message import Message
     msg = Message()
     msg.set_payload("I am full of happy babies.  All days for Me!")
     fut = self._make_one()
     self.assertEqual(fut(msg),
                      "body_regexp: body matches u'happy.+days'")
Example #10
0
 def test_as_message_attachments(self):
     msg_in = Message()
     msg_in["From"] = "*****@*****.**"
     msg_in["Message-ID"] = "<msg>"
     msg_in.attach(MIMEText("Dummy message"))
     msg_in.attach(MIMEText("<html><body>Dummy message</body></html>", _subtype="html"))
     add_to_list("*****@*****.**", msg_in)
     email = Email.objects.get(message_id="msg")
     msg = email.as_message()
     self.assertEqual(msg["From"], "dummy at example.com")
     self.assertEqual(msg["Message-ID"], "<msg>")
     self.assertTrue(msg.is_multipart())
     payload = msg.get_payload()
     self.assertEqual(len(payload), 2)
     self.assertEqual(
         payload[0].get_payload(decode=True).strip(), "Dummy message")
     # The filename extension detection from content type is a bit random
     # (depends on the PYTHON_HASHSEED), make sure we get the right one
     # here for testing.
     expected_ext = guess_all_extensions("text/html", strict=False)[0]
     self.assertEqual(payload[1].get_content_type(), "text/html")
     self.assertEqual(payload[1]["Content-Disposition"],
         'attachment; filename="attachment%s"' % expected_ext)
     self.assertEqual(
         payload[1].get_payload(decode=True),
         "<html><body>Dummy message</body></html>")
Example #11
0
 def message_to_string(self, recever_addr, title, text):
     message = Message()
     message['From'] = self.from_addr
     message['Subject'] = title
     message['To'] = recever_addr
     message.set_payload(text, charset='utf-8')
     return message.as_string()
Example #12
0
 def _cloneMessage(self, message):
     clone = Message()
     for key, value in message.items():
         if key.lower() != 'message-id':
             clone[key] = value
     clone.set_payload(message.get_payload())
     return clone
 def test_payload_encoding(self):
     jhello = '\xa5\xcf\xa5\xed\xa1\xbc\xa5\xef\xa1\xbc\xa5\xeb\xa5\xc9\xa1\xaa'
     jcode  = 'euc-jp'
     msg = Message()
     msg.set_payload(jhello, jcode)
     ustr = unicode(msg.get_payload(), msg.get_content_charset())
     self.assertEqual(jhello, ustr.encode(jcode))
Example #14
0
def send_mail(subject, content):

    smtpserver = 'smtp.gmail.com'
    username = '******'
    password = '******'

    from_addr = '*****@*****.**'
    to_addr = '*****@*****.**'

    mailtime = email.utils.formatdate(time.time(), True)

    message = Message()
    message['Subject'] = subject
    message['From'] = from_addr
    message['To'] = to_addr

    mailcontent = "\nQuery Time: {0}\n\n{1}\n\n".format(mailtime, content)

    message.set_payload(mailcontent)
    msg = message.as_string()

    sm = smtplib.SMTP(smtpserver, port=587, timeout=20)
    sm.set_debuglevel(1)
    sm.ehlo()
    sm.starttls()
    sm.ehlo()
    sm.login(username, password)

    sm.sendmail(from_addr, to_addr, msg)
    sleep(5)
    sm.quit()
Example #15
0
 def test_no_from(self):
     msg = Message()
     msg.set_payload("Dummy message")
     try:
         name, email = utils.parseaddr(msg["From"])
     except AttributeError, e:
         self.fail(e)
Example #16
0
def register_view(context, request):
    form = Form(Signup(), buttons=('register',))
    rendered_form = form.render(null)
    if 'register' in request.POST:
        try:
            appstruct = form.validate(request.POST.items())
        except ValidationFailure, e:
            rendered_form = e.render()
        else:
            pending = request.registry.queryAdapter(context, IRegistrations,
                                                    name='pending')
            if pending is None:  #pragma NO COVERAGE
                pending = PendingRegistrations(context)
            email = appstruct['email']
            token = getRandomToken(request)
            pending.set(email, token=token)

            from_addr = request.registry.settings['cartouche.from_addr']
            delivery = request.registry.queryUtility(IMailDelivery,
                                                     default=localhost_mta)
            confirmation_url = view_url(context, request, 'confirmation_url',
                                        'confirm_registration.html',
                                        email=email)
            body = REGISTRATION_EMAIL % {'token': token,
                                         'confirmation_url': confirmation_url}
            message = Message()
            message['Subject'] = 'Site registration confirmation'
            message.set_payload(body)
            delivery.send(from_addr, [email], message)
            return HTTPFound(location=confirmation_url)
 def _add_message(self, msgid="msg"):
     msg = Message()
     msg["From"] = "Dummy Sender <*****@*****.**>"
     msg["Message-ID"] = "<%s>" % msgid
     msg["Subject"] = "Dummy message"
     msg.set_payload("Dummy content with keyword")
     return add_to_list("*****@*****.**", msg)
Example #18
0
 def setUp(self):
     # Create the list by adding a dummy message
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<msg>"
     msg.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg)
Example #19
0
 def test_get_threads_between(self):
     # the get_threads_between method should return all threads that have
     # been active between the two specified dates, including the threads
     # started in between those dates but updated later
     msg1 = Message()
     msg1["From"] = "*****@*****.**"
     msg1["Message-ID"] = "<msg1>"
     msg1["Date"] = "2015-02-15 00:00:00 UTC"
     msg1.set_payload("message 1")
     add_to_list(self.ml.name, msg1)
     # The thread started in Feb, it should show up in the Feb threads but
     # not in the January or March threads.
     self.assertEqual(Thread.objects.count(), 1)
     jan_threads = self.ml.get_threads_between(
         datetime(2015, 1, 1, 0, 0, 0, tzinfo=utc),
         datetime(2015, 1, 31, 0, 0, 0, tzinfo=utc),
         )
     self.assertEqual(jan_threads.count(), 0)
     feb_threads = self.ml.get_threads_between(
         datetime(2015, 2, 1, 0, 0, 0, tzinfo=utc),
         datetime(2015, 2, 28, 0, 0, 0, tzinfo=utc),
         )
     self.assertEqual(feb_threads.count(), 1)
     march_threads = self.ml.get_threads_between(
         datetime(2015, 3, 1, 0, 0, 0, tzinfo=utc),
         datetime(2015, 3, 31, 0, 0, 0, tzinfo=utc),
         )
     self.assertEqual(march_threads.count(), 0)
Example #20
0
 def test_since_override(self):
     # When there's mail already and the "since" option is not used, it
     # defaults to the last email's date
     msg1 = Message()
     msg1["From"] = "*****@*****.**"
     msg1["Message-ID"] = "<msg1>"
     msg1["Date"] = "2015-01-01 12:00:00"
     msg1.set_payload("msg1")
     add_to_list("*****@*****.**", msg1)
     mailbox.mbox(os.path.join(self.tmpdir, "test.mbox"))
     # do the import
     output = StringIO()
     with patch("hyperkitty.management.commands.hyperkitty_import.DbImporter"
         ) as DbImporterMock:
         instance = Mock()
         instance.impacted_thread_ids = []
         DbImporterMock.side_effect = lambda *a, **kw: instance
         self.command.execute(os.path.join(self.tmpdir, "test.mbox"),
             verbosity=2, stdout=output, stderr=output,
             list_address="*****@*****.**",
             since="2010-01-01 00:00:00 UTC",
             no_download=True, no_sync_mailman=True,
         )
     self.assertEqual(DbImporterMock.call_args[0][1]["since"],
                      datetime(2010, 1, 1, tzinfo=utc))
Example #21
0
    def test_delivery(self):
        from email.message import Message
        from_addr = "*****@*****.**"
        to_addr = "*****@*****.**"
        message = Message()
        message['Subject'] = 'Pants'
        message.set_payload('Nice pants, mister!')

        import transaction
        transaction.manager.begin()
        self.delivery.send(from_addr, to_addr, message)
        self.delivery.send(from_addr, to_addr, message)
        transaction.manager.commit()

        queued_messages = [m for m in self.maildir]
        self.assertEqual(2, len(queued_messages))
        self.assertEqual(0, len(self.mailer.sent_messages))

        cmdline = "qp %s" % self.queue_dir
        app = ConsoleApp(cmdline.split())
        app.mailer = self.mailer
        app.main()

        queued_messages = [m for m in self.maildir]
        self.assertEqual(0, len(queued_messages))
        self.assertEqual(2, len(self.mailer.sent_messages))
Example #22
0
 def test_wrong_encoding(self):
     """badly encoded message, only fails on PostgreSQL"""
     db_engine = settings.DATABASES[DEFAULT_DB_ALIAS]["ENGINE"]
     if db_engine == "django.db.backends.sqlite3":
         raise SkipTest # SQLite will accept anything
     with open(get_test_file("payload-utf8-wrong.txt")) as email_file:
         msg = message_from_file(email_file)
     mbox = mailbox.mbox(os.path.join(self.tmpdir, "test.mbox"))
     mbox.add(msg)
     # Second message
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<msg1>"
     msg["Date"] = "2015-02-01 12:00:00"
     msg.set_payload("msg1")
     mbox.add(msg)
     # do the import
     output = StringIO()
     kw = self.common_cmd_args.copy()
     kw["stdout"] = kw["stderr"] = output
     self.command.execute(os.path.join(self.tmpdir, "test.mbox"), **kw)
     # Message 1 must have been rejected, but no crash
     self.assertIn("Message wrong.encoding failed to import, skipping",
                   output.getvalue())
     # Message 2 must have been accepted
     self.assertEqual(MailingList.objects.count(), 1)
     self.assertEqual(Email.objects.count(), 1)
Example #23
0
 def test_delete_single_in_thread(self):
     # Delete an email in a thread that contains other emails
     self.user.is_staff = True
     self.user.save()
     msg = Email.objects.get(message_id="msg")
     msg2 = Message()
     msg2["From"] = "*****@*****.**"
     msg2["Message-ID"] = "<msg2>"
     msg2["In-Reply-To"] = "<msg>"
     msg2.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg2)
     msg2 = Email.objects.get(message_id="msg2")
     thread_id = msg.thread.thread_id
     url = reverse('hk_message_delete',
                   args=("*****@*****.**", msg.message_id_hash))
     response = self.client.post(url, {"email": msg.pk})
     self.assertRedirects(
         response, reverse('hk_thread', kwargs={
             "mlist_fqdn": "*****@*****.**",
             "threadid": thread_id}))
     # Flash message
     messages = get_flash_messages(response)
     self.assertEqual(len(messages), 1)
     self.assertEqual(messages[0].tags, "success")
     # The message must be deleted, but not the other message or the thread.
     self.assertFalse(Email.objects.filter(message_id="msg").exists())
     self.assertTrue(Email.objects.filter(message_id="msg2").exists())
     thread = Thread.objects.get(thread_id=thread_id)
     self.assertIsNotNone(thread)
     # msg2 must now be the thread starter.
     msg2.refresh_from_db()
     self.assertIsNone(msg2.parent_id)
     self.assertEqual(thread.starting_email.message_id, "msg2")
def handler(doc):
    # a 'rfc822' stores 'headers' as a dict, with each entry being a list.
    # We only care about headers which rfc5322 must appear 0 or 1 times, so
    # flatten the header values here...
    headers = dict((k, v[0]) for (k, v) in doc['headers'].iteritems())
    # for now, 'from' etc are all tuples of [identity_type, identity_id]
    callbacks = []
    ret = {}
    if 'from' in headers:
        name, addr = parseaddr(headers['from'])
        ret['from'] = ['email', addr.lower()]
        ret['from_display'] = name

    if 'to' in headers:
        id_list = ret['to'] = []
        disp_list = ret['to_display'] = []
        fill_identity_info(headers['to'], id_list, disp_list)

    if 'cc' in headers:
        id_list = ret['cc'] = []
        disp_list = ret['cc_display'] = []
        fill_identity_info(headers['cc'], id_list, disp_list)

    if 'subject' in headers:
        ret['subject'] = headers['subject']
    if 'timestamp' in doc:
        ret['timestamp'] = doc['timestamp']

    # body handling
    if doc.get('multipart'):
        infos = doc['multipart_info']
    else:
        aname, attach = get_schema_attachment_info(doc, 'body')
        infos = [{'content_type': attach['content_type'],
                  'name': 'body'}]

    parts = []
    docid = doc['_id']
    for info in infos:
        # Use the email package to help parse the charset...
        m = Message()
        m['content-type'] = info['content_type']
        charset = m.get_content_charset()
        ct = m.get_content_type()
        if ct == 'text/plain':
            name = info['name']
            content = open_schema_attachment(doc, name)
            parts.append(decode_body_part(docid, content, charset))

        # else: we should annotate the object with non-plaintext
        # attachment information XXX
    ret['body'] = '\n'.join(parts)

    ret['body_preview'] = extract_preview(ret['body'])
    try:
        # If the provider could supply tags then pass them on
        ret['tags'] = doc['tags']
    except KeyError:
        pass
    emit_schema('rd.msg.body', ret)
Example #25
0
    def urlgetcontent(self, container, url, data = None, method = None, headers = {}, tostr = False,  encoding = None, rawurl = False, *args, **kwargs):
        '''
        In Python2, bytes = str, so tostr and encoding has no effect.
        In Python3, bytes are decoded into unicode str with encoding.
        If encoding is not specified, charset in content-type is used if present, or default to utf-8 if not.
        See open for available arguments

        :param rawurl: if True, assume the url is already url-encoded, do not encode it again.
        '''
        req = Request(url, data, method, headers, rawurl = rawurl)
        for m in self.open(container, req, *args, **kwargs):
            yield m
        resp = container.retvalue
        encoding = 'utf-8'
        if encoding is None:
            m = Message()
            m.add_header('Content-Type', resp.get_header('Content-Type', 'text/html'))
            encoding = m.get_content_charset('utf-8')
        if not resp.stream:
            content = b''
        else:
            for m in resp.stream.read(container):
                yield m
            content = container.data
        if tostr:
            content = _str(content, encoding)
        container.retvalue = content
Example #26
0
 def generate_msg(self, code, sendid):
     msg = Message()
     msg.set_payload(code)
     msg['Subject'] = 'Rummager (sendid: %s)' % (sendid,)
     msg['From'] = '*****@*****.**'
     msg['To'] = '*****@*****.**'
     return msg
Example #27
0
def recover_account_view(context, request):
    form = Form(RecoverAccount(), buttons=('recover',))
    rendered_form = form.render(null)
    confirmed = request.registry.queryAdapter(context, IRegistrations,
                                              name='confirmed')
    if confirmed is None:  #pragma NO COVERAGE
        confirmed = ConfirmedRegistrations(context)
    login_url = view_url(context, request, 'login_url', 'login.html')
    registry = request.registry
    message = request.GET.get('message')

    if 'recover' in request.POST:
        try:
            appstruct = form.validate(request.POST.items())
        except ValidationFailure, e: #pragma NO COVER
            rendered_form = e.render()
        else:
            email = appstruct['email']
            record = confirmed.get_by_email(email)
            if record is not None:
                from_addr = registry.settings['cartouche.from_addr']
                login = record.login
                body = RECOVERY_EMAIL % {'login': login,
                                         'login_url': login_url}
                delivery = registry.queryUtility(IMailDelivery,
                                                 default=localhost_mta)
                email_message = Message()
                email_message['Subject'] = 'Account recovery'
                email_message.set_payload(body)
                delivery.send(from_addr, [email], email_message)
            #else: # DO NOT report lookup errors
            return HTTPFound(location=login_url)
Example #28
0
 def test_delete_all_messages_in_thread(self):
     self.user.is_staff = True
     self.user.save()
     msg = Email.objects.get(message_id="msg")
     msg2 = Message()
     msg2["From"] = "*****@*****.**"
     msg2["Message-ID"] = "<msg2>"
     msg2["In-Reply-To"] = "<msg>"
     msg2.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg2)
     msg2 = Email.objects.get(message_id="msg2")
     thread_id = msg.thread.pk
     url = reverse('hk_thread_delete',
                   args=("*****@*****.**", msg.thread.thread_id))
     response = self.client.post(url, {"email": [msg.pk, msg2.pk]})
     self.assertRedirects(
         response, reverse('hk_list_overview', kwargs={
             "mlist_fqdn": "*****@*****.**"}))
     # Flash message
     messages = get_flash_messages(response)
     self.assertEqual(len(messages), 1)
     self.assertEqual(messages[0].tags, "success")
     # Alls messages and the thread must be deleted.
     self.assertFalse(Email.objects.filter(message_id="msg").exists())
     self.assertFalse(Email.objects.filter(message_id="msg2").exists())
     self.assertFalse(Thread.objects.filter(pk=thread_id).exists())
Example #29
0
	def post(self, folder, subject="", body="", date=None, headers={}, metadata={}):
		folder_name = self.select_or_create_folder(folder)
		# create the post as a new email
		m = Message()
		m["From"] = self.email
		# m["To"] = "*****@*****.**"
		m["Content-Type"] = "text/plain"
		if subject:
			m["Subject"] = subject
		# Javascript should use d.toString() = "Sun Jun 09 2013 16:21:47 GMT+0800 (WST)"
		msg_time = (date and dateutil.parser.parse(date) or None)
		if msg_time:
			# Date - 
			# djb nails it:
			# http://cr.yp.to/immhf/date.html
			# Date: 23 Dec 1995 19:25:43 -0000
			m["Date"] = msg_time.strftime("%a, %d %b %Y %X %z")
		# set any other headers
		for h in headers:
			m[h] = headers[h]
		for md in metadata:
			m[json_marker + md] = json.dumps(metadata[md])
		# set the content of the message
		if body:
			m.set_payload(body)
		response = self.append(folder_name, m.as_string(), msg_time=msg_time)
		#print response
		# u'[APPENDUID 594556012 1] (Success)'
		# u'[APPENDUID 1370766584 11] Append completed.'
		result = {"message": None, "codes": []}
		if append_response_re.match(response):
			result = append_response_re.match(response).groupdict()
			result["codes"] = result["codes"].split(" ")
			result["UID"] = int(result["codes"][:].pop())
		return result, m
Example #30
0
    def process(self, message: Message):
        """Displays desktop notification about specified message.

        :param message: E-Mail message object.
        """

        print("  - {}: {}.process()".format(self.name, self.__class__.__name__))

        notify2.init("Sendmail")

        title = self.title_template.format(
            subject=message.get("Subject"),
            from_email=message.get("From"),
            appname="Sendmail",
            name=self.name
        )
        text = self.text_template.format(
            subject=message.get("Subject"),
            from_email=message.get("From"),
            text=message.as_string(),
            appname="Sendmail",
            name=self.name
        )

        n = notify2.Notification(title,
            text,
            self.icon_name
        )

        n.show()
Example #31
0
    def prepare_multipart_body(self):
        # type: () -> None
        """Will prepare the body of this request according to the multipart information.

        This call assumes the on_request policies have been applied already in their
        correct context (sync/async)

        Does nothing if "set_multipart_mixed" was never called.
        """
        if not self.multipart_mixed_info:
            return

        requests = self.multipart_mixed_info[0]  # type: List[HttpRequest]
        boundary = self.multipart_mixed_info[2]  # type: Optional[str]

        # Update the main request with the body
        main_message = Message()
        main_message.add_header("Content-Type", "multipart/mixed")
        if boundary:
            main_message.set_boundary(boundary)
        for i, req in enumerate(requests):
            part_message = Message()
            part_message.add_header("Content-Type", "application/http")
            part_message.add_header("Content-Transfer-Encoding", "binary")
            part_message.add_header("Content-ID", str(i))
            part_message.set_payload(req.serialize())
            main_message.attach(part_message)

        try:
            from email.policy import HTTP

            full_message = main_message.as_bytes(policy=HTTP)
            eol = b"\r\n"
        except ImportError:  # Python 2.7
            # Right now we decide to not support Python 2.7 on serialization, since
            # it doesn't serialize a valid HTTP request (and our main scenario Storage refuses it)
            raise NotImplementedError(
                "Multipart request are not supported on Python 2.7"
            )
            # full_message = main_message.as_string()
            # eol = b'\n'
        _, _, body = full_message.split(eol, 2)
        self.set_bytes_body(body)
        self.headers["Content-Type"] = (
            "multipart/mixed; boundary=" + main_message.get_boundary()
        )
Example #32
0
 def __setitem__(self, name, value):
     rc = Message.__setitem__(self, name, value)
     self.modified = True
     if self.headerchange: self.headerchange(self, name, str(value))
     return rc
Example #33
0
    def parse_pgpmime(self, message):
        sig_count, sig_parts, sig_alg = 0, [], 'SHA1'
        enc_count, enc_parts, enc_ver = 0, [], None

        for part in message.walk():
            mimetype = part.get_content_type()
            if (sig_count > 1) and (mimetype == 'application/pgp-signature'):
                sig = part.get_payload()
                msg = '\r\n'.join(
                    sig_parts[0].as_string().splitlines(False)) + '\r\n'

                result = None
                gpg = GnuPG()
                status = gpg.verify(msg, sig)
                print status

                for sig_part in sig_parts:
                    print "sig_part: ", dir(sig_part), type(sig_part)
                    sig_part.openpgp = ("signed", status)
                    part.openpgp = ("signed", status)

                # Reset!
                sig_count, sig_parts = 0, []

            elif sig_count > 0:
                sig_parts.append(part)
                sig_count += 1

            elif enc_count > 0 and (mimetype == 'application/octet-stream'):
                # FIXME: Decrypt and parse!
                crypt = tempfile.NamedTemporaryFile()
                crypt.write(part.get_payload())
                crypt.flush()
                msg = '\r\n'.join(part.as_string().splitlines(False)) + '\r\n'

                result = None
                gpg = GnuPG()
                res, result = gpg.decrypt(msg)
                if res == 0:
                    summary = ('decrypted', result)
                else:
                    summary = ('encrypted', result)
                s = StringIO.StringIO()
                s.write(result)
                m = Parser().parse(s)
                m = Message()
                m.set_payload(result)
                part.set_payload([m])
                part.openpgp = summary

                for enc_part in enc_parts:
                    enc_part.openpgp = summary

                # Reset!
                enc_count, enc_parts = 0, []

            elif mimetype == 'multipart/signed':
                sig_alg = part.get_param('micalg',
                                         'pgp-sha1').split('-')[-1].upper()
                sig_count = 1

            elif mimetype == 'multipart/encrypted':
                enc_count = 1
Example #34
0
 def set_payload(self, payload, charset=None):
     payload = payload.encode('utf-8')
     Message.set_payload(self, payload, self.get_charset())
Example #35
0
    def send(self, job, message, config=None):
        """
        Sends mail using configured mail settings.

        If `attachments` is true, a list compromised of the following dict is required
        via HTTP upload:
          - headers(list)
            - name(str)
            - value(str)
            - params(dict)
          - content (str)

        [
         {
          "headers": [
           {
            "name": "Content-Transfer-Encoding",
            "value": "base64"
           },
           {
            "name": "Content-Type",
            "value": "application/octet-stream",
            "params": {
             "name": "test.txt"
            }
           }
          ],
          "content": "dGVzdAo="
         }
        ]
        """

        syslog.openlog(logoption=syslog.LOG_PID, facility=syslog.LOG_MAIL)
        interval = message.get('interval')
        if interval is None:
            interval = timedelta()
        else:
            interval = timedelta(seconds=interval)

        sw_name = self.middleware.call_sync('system.info')['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')

        if not config:
            config = self.middleware.call_sync('mail.config')
        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')

        def read_json():
            f = os.fdopen(job.read_fd, 'rb')
            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() if message.get('attachments') else None
        if attachments:
            msg = MIMEMultipart()
            msg.preamble = message['text']
            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')

        subject = message.get('subject')
        if subject:
            msg['Subject'] = subject

        msg['From'] = config['fromemail']
        msg['To'] = ', '.join(to)
        msg['Date'] = formatdate()

        local_hostname = socket.gethostname()

        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()):
            if key in msg:
                msg.replace_header(key, val)
            else:
                msg[key] = val

        try:
            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()
            syslog.syslog("sending mail to " + ','.join(to) +
                          msg.as_string()[0:140])
            server.sendmail(config['fromemail'], to, msg.as_string())
            server.quit()
        except ValueError as ve:
            # Don't spam syslog with these messages. They should only end up in the
            # test-email pane.
            raise CallError(str(ve))
        except smtplib.SMTPAuthenticationError as e:
            raise CallError(
                f'Authentication error ({e.smtp_code}): {e.smtp_error}',
                errno.EAUTH)
        except Exception as e:
            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 #36
0
    def apply(self, ui):
        # get message to forward if not given in constructor
        if not self.message:
            self.message = ui.current_buffer.get_selected_message()
        mail = self.message.get_email()

        envelope = Envelope()

        if self.inline:  # inline mode
            # set body text
            name, address = self.message.get_author()
            timestamp = self.message.get_date()
            qf = settings.get_hook('forward_prefix')
            if qf:
                quote = qf(name, address, timestamp, ui=ui, dbm=ui.dbman)
            else:
                quote = 'Forwarded message from %s (%s):\n' % (name or address,
                                                               timestamp)
            mailcontent = quote
            quotehook = settings.get_hook('text_quote')
            if quotehook:
                mailcontent += quotehook(self.message.accumulate_body())
            else:
                quote_prefix = settings.get('quote_prefix')
                for line in self.message.accumulate_body().splitlines():
                    mailcontent += quote_prefix + line + '\n'

            envelope.body = mailcontent

            for a in self.message.get_attachments():
                envelope.attach(a)

        else:  # attach original mode
            # attach original msg
            original_mail = Message()
            original_mail.set_type('message/rfc822')
            original_mail['Content-Disposition'] = 'attachment'
            original_mail.set_payload(email_as_string(mail))
            envelope.attach(Attachment(original_mail))

        # copy subject
        subject = decode_header(mail.get('Subject', ''))
        subject = 'Fwd: ' + subject
        forward_subject_hook = settings.get_hook('forward_subject')
        if forward_subject_hook:
            subject = forward_subject_hook(subject)
        else:
            fsp = settings.get('forward_subject_prefix')
            if not subject.startswith(('Fwd:', fsp)):
                subject = fsp + subject
        envelope.add('Subject', subject)

        # set From-header and sending account
        try:
            from_header, account = determine_sender(mail, 'reply')
        except AssertionError as e:
            ui.notify(e.message, priority='error')
            return
        envelope.add('From', from_header)

        # continue to compose
        ui.apply_command(
            ComposeCommand(envelope=envelope, spawn=self.force_spawn))
Example #37
0
def recognise():
    stream = request.stream

    #=== This is the part I took out ===#
    # access_token, part1, part2 = request.host.split('.', 1)[0].split('-', 3)
    # lang = f"{part1}-{part2.upper()}"

    # auth_req = requests.get(f"{AUTH_URL}/api/v1/me/token", headers={'Authorization': f"Bearer {access_token}"})
    # if not auth_req.ok:
    #     abort(401)
    #=== --------------------------- ===#

    chunks = iter(list(parse_chunks(stream)))
    content = next(chunks).decode('utf-8')

    body = {
        'config': {
            'encoding': 'SPEEX_WITH_HEADER_BYTE',
            'language_code': 'en-US',  # hardcoded
            'sample_rate_hertz': 16000,
            'max_alternatives': 1,
            'enableAutomaticPunctuation': True,
            # 'metadata': {
            #     'interaction_type': 'DICTATION',
            #     'microphone_distance': 'NEARFIELD',
            # },
        },
        'audio': {
            'content':
            base64.b64encode(b''.join((struct.pack('B', len(x)) + x
                                       for x in chunks))).decode('utf-8'),
        },
    }
    result = requests.post(
        f'https://speech.googleapis.com/v1/speech:recognize?key={API_KEY}',
        json=body)
    result.raise_for_status()

    words = []
    if 'results' in result.json():
        for result in result.json()['results']:
            words.extend(
                {
                    'word': x,
                    'confidence': str(result['alternatives'][0]['confidence']),
                } for x in result['alternatives'][0]['transcript'].split(' '))

    # Now for some reason we also need to give back a mime/multipart message...
    parts = MIMEMultipart()
    response_part = Message()
    response_part.add_header('Content-Type', 'application/JSON; charset=utf-8')

    if len(words) > 0:
        response_part.add_header('Content-Disposition',
                                 'form-data; name="QueryResult"')
        words[0]['word'] += '\\*no-space-before'
        words[0]['word'] = words[0]['word'][0].upper() + words[0]['word'][1:]
        response_part.set_payload(json.dumps({
            'words': [words],
        }))
    else:
        response_part.add_header('Content-Disposition',
                                 'form-data; name="QueryRetry"')
        # Other errors probably exist, but I don't know what they are.
        # This is a Nuance error verbatim.
        response_part.set_payload(
            json.dumps({
                "Cause":
                1,
                "Name":
                "AUDIO_INFO",
                "Prompt":
                "Sorry, speech not recognized. Please try again."
            }))
    parts.attach(response_part)

    parts.set_boundary('--Nuance_NMSP_vutc5w1XobDdefsYG3wq')

    response = Response(
        '\r\n' + parts.as_string().split("\n", 3)[3].replace('\n', '\r\n'))
    response.headers[
        'Content-Type'] = f'multipart/form-data; boundary={parts.get_boundary()}'
    return response
Example #38
0
    def _get_dehydrated_message(self, msg, record):
        settings = utils.get_settings()

        new = EmailMessage()
        if msg.is_multipart():
            for header, value in msg.items():
                new[header] = value
            for part in msg.get_payload():
                new.attach(self._get_dehydrated_message(part, record))
        elif (settings['strip_unallowed_mimetypes']
              and not msg.get_content_type() in settings['allowed_mimetypes']):
            for header, value in msg.items():
                new[header] = value
            # Delete header, otherwise when attempting to  deserialize the
            # payload, it will be expecting a body for this.
            del new['Content-Transfer-Encoding']
            new[settings['altered_message_header']] = (
                'Stripped; Content type %s not allowed' %
                (msg.get_content_type()))
            new.set_payload('')
        elif ((msg.get_content_type() not in settings['text_stored_mimetypes'])
              or ('attachment' in msg.get('Content-Disposition', ''))):
            filename = None
            raw_filename = msg.get_filename()
            if raw_filename:
                filename = utils.convert_header_to_unicode(raw_filename)
            if not filename:
                extension = mimetypes.guess_extension(msg.get_content_type())
            else:
                _, extension = os.path.splitext(filename)
            if not extension:
                extension = '.bin'

            attachment = MessageAttachment()

            attachment.document.save(
                uuid.uuid4().hex + extension,
                ContentFile(BytesIO(msg.get_payload(decode=True)).getvalue()))
            attachment.message = record
            for key, value in msg.items():
                attachment[key] = value
            attachment.save()

            placeholder = EmailMessage()
            placeholder[settings['attachment_interpolation_header']] = str(
                attachment.pk)
            new = placeholder
        else:
            content_charset = msg.get_content_charset()
            if not content_charset:
                content_charset = 'ascii'
            try:
                # Make sure that the payload can be properly decoded in the
                # defined charset, if it can't, let's mash some things
                # inside the payload :-\
                msg.get_payload(decode=True).decode(content_charset)
            except LookupError:
                logger.warning("Unknown encoding %s; interpreting as ASCII!",
                               content_charset)
                msg.set_payload(
                    msg.get_payload(decode=True).decode('ascii', 'ignore'))
            except ValueError:
                logger.warning(
                    "Decoding error encountered; interpreting %s as ASCII!",
                    content_charset)
                msg.set_payload(
                    msg.get_payload(decode=True).decode('ascii', 'ignore'))
            new = msg
        return new
Example #39
0
def cb_action_REJECT(module, filepath):
    log.info(_("Rejecting message in %s (by module %s)") % (filepath, module))

    # parse message headers
    message = Parser().parse(open(filepath, 'r'), True)

    envelope_sender = getaddresses(message.get_all('From', []))

    recipients = getaddresses(message.get_all('To', [])) + \
            getaddresses(message.get_all('Cc', [])) + \
            getaddresses(message.get_all('X-Kolab-To', []))

    _recipients = []

    for recipient in recipients:
        if not recipient[0] == '':
            _recipients.append('%s <%s>' % (recipient[0], recipient[1]))
        else:
            _recipients.append('%s' % (recipient[1]))

    # TODO: Find the preferredLanguage for the envelope_sender user.
    ndr_message_subject = "Undelivered Mail Returned to Sender"
    ndr_message_text = _("""This is the email system Wallace at %s.

I'm sorry to inform you we could not deliver the attached message
to the following recipients:

- %s

Your message is being delivered to any other recipients you may have
sent your message to. There is no need to resend the message to those
recipients.
""") % (constants.fqdn, "\n- ".join(_recipients))

    diagnostics = _("""X-Wallace-Module: %s
X-Wallace-Result: REJECT
""") % (module)

    msg = MIMEMultipart("report")
    msg['From'] = "MAILER-DAEMON@%s" % (constants.fqdn)
    msg['To'] = formataddr(envelope_sender[0])
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = ndr_message_subject

    msg.preamble = "This is a MIME-encapsulated message."

    part = MIMEText(ndr_message_text)
    part.add_header("Content-Description", "Notification")
    msg.attach(part)

    _diag_message = Message()
    _diag_message.set_payload(diagnostics)
    part = MIMEMessage(_diag_message, "delivery-status")
    part.add_header("Content-Description", "Delivery Report")
    msg.attach(part)

    # @TODO: here I'm not sure message will contain the whole body
    # when we used headersonly argument of Parser().parse() above
    # delete X-Kolab-* headers
    del message['X-Kolab-From']
    del message['X-Kolab-To']

    part = MIMEMessage(message)
    part.add_header("Content-Description", "Undelivered Message")
    msg.attach(part)

    result = _sendmail("MAILER-DAEMON@%s" % (constants.fqdn),
                       [formataddr(envelope_sender[0])], msg.as_string())

    if result:
        os.unlink(filepath)
Example #40
0
    def _rehydrate(self, msg):
        new = EmailMessage()
        settings = utils.get_settings()

        if msg.is_multipart():
            for header, value in msg.items():
                new[header] = value
            for part in msg.get_payload():
                new.attach(self._rehydrate(part))
        elif settings['attachment_interpolation_header'] in msg.keys():
            try:
                attachment = MessageAttachment.objects.get(
                    pk=msg[settings['attachment_interpolation_header']])
                for header, value in attachment.items():
                    new[header] = value
                encoding = new['Content-Transfer-Encoding']
                if encoding and encoding.lower() == 'quoted-printable':
                    # Cannot use `email.encoders.encode_quopri due to
                    # bug 14360: http://bugs.python.org/issue14360
                    output = BytesIO()
                    encode_quopri(
                        BytesIO(attachment.document.read()),
                        output,
                        quotetabs=True,
                        header=False,
                    )
                    new.set_payload(output.getvalue().decode().replace(
                        ' ', '=20'))
                    del new['Content-Transfer-Encoding']
                    new['Content-Transfer-Encoding'] = 'quoted-printable'
                else:
                    new.set_payload(attachment.document.read())
                    del new['Content-Transfer-Encoding']
                    encode_base64(new)
            except MessageAttachment.DoesNotExist:
                new[settings['altered_message_header']] = (
                    'Missing; Attachment %s not found' %
                    (msg[settings['attachment_interpolation_header']]))
                new.set_payload('')
        else:
            for header, value in msg.items():
                new[header] = value
            new.set_payload(msg.get_payload())
        return new
Example #41
0
 def add_payload(message, obj):
     payload = Message()
     encoding = obj.get("encoding", "utf-8")
     if encoding and (encoding.upper() in
                      ("BASE64", "7BIT", "8BIT", "BINARY")):
         payload.add_header("Content-Transfer-Encoding", encoding)
     else:
         payload.set_charset(encoding)
     mime = obj.get("mime", None)
     if mime:
         payload.set_type(mime)
     if "text" in obj:
         payload.set_payload(obj["text"])
     elif "payload" in obj:
         payload.set_payload(obj["payload"])
     if "filename" in obj and obj["filename"]:
         payload.add_header("Content-Disposition",
             "attachment", filename=obj["filename"])
     message.attach(payload)
Example #42
0
    def createEmail(self,
                    msgdict,
                    builderName,
                    title,
                    results,
                    builds=None,
                    patches=None,
                    logs=None):
        text = msgdict['body'].encode(ENCODING)
        type = msgdict['type']
        if 'subject' in msgdict:
            subject = msgdict['subject'].encode(ENCODING)
        else:
            subject = self.subject % {
                'result': Results[results],
                'projectName': title,
                'title': title,
                'builder': builderName
            }

        assert '\n' not in subject, \
            "Subject cannot contain newlines"

        assert type in ('plain', 'html'), \
            "'%s' message type must be 'plain' or 'html'." % type

        if patches or logs:
            m = MIMEMultipart()
            txt = MIMEText(text, type, ENCODING)
            m.attach(txt)
        else:
            m = Message()
            m.set_payload(text, ENCODING)
            m.set_type("text/%s" % type)

        m['Date'] = formatdate(localtime=True)
        m['Subject'] = subject
        m['From'] = self.fromaddr
        # m['To'] is added later

        if patches:
            for (i, patch) in enumerate(patches):
                a = self.patch_to_attachment(patch, i)
                m.attach(a)
        if logs:
            for log in logs:
                name = "%s.%s" % (log['stepname'], log['name'])
                if (self._shouldAttachLog(log['name'])
                        or self._shouldAttachLog(name)):
                    # Use distinct filenames for the e-mail summary
                    if self.buildSetSummary:
                        filename = "%s.%s" % (log['buildername'], name)
                    else:
                        filename = name

                    text = log['content']['content']
                    a = MIMEText(text.encode(ENCODING), _charset=ENCODING)
                    a.add_header('Content-Disposition',
                                 "attachment",
                                 filename=filename)
                    m.attach(a)

        # @todo: is there a better way to do this?
        # Add any extra headers that were requested, doing WithProperties
        # interpolation if only one build was given
        if self.extraHeaders:
            extraHeaders = self.extraHeaders
            if len(builds) == 1:
                props = Properties.fromDict(builds[0]['properties'])
                extraHeaders = yield props.render(extraHeaders)

            for k, v in iteritems(extraHeaders):
                if k in m:
                    twlog.msg("Warning: Got header " + k +
                              " in self.extraHeaders "
                              "but it already exists in the Message - "
                              "not adding it.")
                m[k] = v
        defer.returnValue(m)
Example #43
0
 def new_message(self):
     from email.message import Message
     return Message()
Example #44
0
import mimetypes
import email.utils
from email.message import Message
import sys, smtplib
import getpass, poplib



#the first part of the program generates some default mail for the mail folder in root.

file1.open('message1.txt', 'w')

text = """Hello,
This is a test message from Chapter 12. I hope you enjoy it!
-- Anonymous"""
msg = Message()
msg['To'] = '*****@*****.**'
msg['From'] = 'Test Sender <*****@*****.**>'
msg['Subject'] = 'Test Message, Chapter 12'
msg.set_payload(text)



#attachment setup
def attachment(filename): 
    fd = open(filename, 'rb') 
    mimetype, mimeencoding = mimetypes.guess_type(filename) 
    if mimeencoding or (mimetype is None): 
        mimetype = 'application/octet-stream' 
    maintype, subtype = mimetype.split('/') 
    if maintype == 'text': 
 def setUp(self):
     super(Direct_BasicPlain, self).setUp()
     self.msg = Message()
Example #46
0
    def insert(self, table, fields):
        def add_payload(message, obj):
            payload = Message()
            encoding = obj.get("encoding", "utf-8")
            if encoding and (encoding.upper() in
                             ("BASE64", "7BIT", "8BIT", "BINARY")):
                payload.add_header("Content-Transfer-Encoding", encoding)
            else:
                payload.set_charset(encoding)
            mime = obj.get("mime", None)
            if mime:
                payload.set_type(mime)
            if "text" in obj:
                payload.set_payload(obj["text"])
            elif "payload" in obj:
                payload.set_payload(obj["payload"])
            if "filename" in obj and obj["filename"]:
                payload.add_header("Content-Disposition",
                    "attachment", filename=obj["filename"])
            message.attach(payload)

        mailbox = table.mailbox
        d = dict(((k.name, v) for k, v in fields))
        date_time = d.get("created") or datetime.datetime.now()
        struct_time = date_time.timetuple()
        if len(d) > 0:
            message = d.get("email", None)
            attachments = d.get("attachments", [])
            content = d.get("content", [])
            flags = " ".join(["\\%s" % flag.capitalize() for flag in
                     ("answered", "deleted", "draft", "flagged",
                      "recent", "seen") if d.get(flag, False)])
            if not message:
                from email.message import Message
                mime = d.get("mime", None)
                charset = d.get("encoding", None)
                message = Message()
                message["from"] = d.get("sender", "")
                message["subject"] = d.get("subject", "")
                message["date"] = self.convert_date(date_time, imf=True)

                if mime:
                    message.set_type(mime)
                if charset:
                    message.set_charset(charset)
                for item in ("to", "cc", "bcc"):
                    value = d.get(item, "")
                    if isinstance(value, basestring):
                        message[item] = value
                    else:
                        message[item] = ";".join([i for i in
                            value])
                if (not message.is_multipart() and
                   (not message.get_content_type().startswith(
                        "multipart"))):
                    if isinstance(content, basestring):
                        message.set_payload(content)
                    elif len(content) > 0:
                        message.set_payload(content[0]["text"])
                else:
                    [add_payload(message, c) for c in content]
                    [add_payload(message, a) for a in attachments]
                message = message.as_string()

            result, data = self.connection.append(mailbox, flags, struct_time, message)
            if result == "OK":
                uid = int(re.findall("\d+", str(data))[-1])
                return self.db(table.uid==uid).select(table.id).first().id
            else:
                raise Exception("IMAP message append failed: %s" % data)
        else:
            raise NotImplementedError("IMAP empty insert is not implemented")
Example #47
0
    def test_sendToInterestedUsers_two_builds(self):
        from email.message import Message
        m = Message()

        mn = MailNotifier(fromaddr="*****@*****.**", lookup=None)
        mn.sendMessage = Mock()

        def fakeGetBuilder(buildername):
            if buildername == builder.name:
                return builder
            return None

        def fakeGetBuildRequests(self, bsid):
            return defer.succeed([{"buildername": "Builder", "brid": 1}])

        builder = Mock()
        builder.name = "Builder"

        build1 = FakeBuildStatus(name="build")
        build1.result = FAILURE
        build1.finished = True
        build1.reason = "testReason"
        build1.builder = builder

        build2 = FakeBuildStatus(name="build")
        build2.result = FAILURE
        build2.finished = True
        build2.reason = "testReason"
        build2.builder = builder

        def fakeCreateEmail(msgdict,
                            builderName,
                            title,
                            results,
                            builds=None,
                            patches=None,
                            logs=None):
            # only concerned with m['To'] and m['CC'], which are added in
            # _got_recipients later
            return defer.succeed(m)

        mn.createEmail = fakeCreateEmail

        self.db = fakedb.FakeDBConnector(self)
        self.db.insertTestData([
            fakedb.SourceStampSet(id=1099),
            fakedb.Buildset(id=99,
                            sourcestampsetid=1099,
                            results=SUCCESS,
                            reason="testReason"),
            fakedb.BuildRequest(id=11, buildsetid=99, buildername='Builder'),
            fakedb.Build(number=0, brid=11),
            fakedb.Build(number=1, brid=11),
            fakedb.Change(changeid=9123),
            fakedb.Change(changeid=9124),
            fakedb.ChangeUser(changeid=9123, uid=1),
            fakedb.ChangeUser(changeid=9124, uid=2),
            fakedb.User(uid=1, identifier="tdurden"),
            fakedb.User(uid=2, identifier="user2"),
            fakedb.UserInfo(uid=1,
                            attr_type='email',
                            attr_data="*****@*****.**"),
            fakedb.UserInfo(uid=2,
                            attr_type='email',
                            attr_data="*****@*****.**")
        ])

        def _getInterestedUsers():
            # 'narrator' in this case is the owner, which tests the lookup
            return ["narrator"]

        build1.getInterestedUsers = _getInterestedUsers
        build2.getInterestedUsers = _getInterestedUsers

        def _getResponsibleUsers():
            return ["Big Bob <*****@*****.**>"]

        build1.getResponsibleUsers = _getResponsibleUsers
        build2.getResponsibleUsers = _getResponsibleUsers

        # fake sourcestamp with relevant user bits
        ss1 = Mock(name="sourcestamp")
        fake_change1 = Mock(name="change")
        fake_change1.number = 9123
        ss1.changes = [fake_change1]
        ss1.patch, ss1.addPatch = None, None

        ss2 = Mock(name="sourcestamp")
        fake_change2 = Mock(name="change")
        fake_change2.number = 9124
        ss2.changes = [fake_change2]
        ss2.patch, ss1.addPatch = None, None

        def fakeGetSSlist(ss):
            return lambda: [ss]

        build1.getSourceStamps = fakeGetSSlist(ss1)
        build2.getSourceStamps = fakeGetSSlist(ss2)

        mn.master = self  # FIXME: Should be FakeMaster
        self.status = mn.master_status = mn.buildMessageDict = Mock()
        mn.master_status.getBuilder = fakeGetBuilder
        mn.buildMessageDict.return_value = {"body": "body", "type": "text"}

        mn.buildMessage(builder.name, [build1, build2], build1.result)
        self.assertEqual(m['To'], "[email protected], [email protected]")
Example #48
0
    def send_raw(self, job, message, config=None):
        interval = message.get('interval')
        if interval is None:
            interval = timedelta()
        else:
            interval = timedelta(seconds=interval)

        sw_name = self.middleware.call_sync('system.info')['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')

        if not config:
            config = self.middleware.call_sync('mail.config')
        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 = message['text']
            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'] = config['fromemail']
        msg['To'] = ', '.join(to)
        if message.get('cc'):
            msg['Cc'] = ', '.join(message.get('cc'))
        msg['Date'] = formatdate()

        local_hostname = socket.gethostname()

        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()):
            if key in msg:
                msg.replace_header(key, val)
            else:
                msg[key] = val

        syslog.openlog(logoption=syslog.LOG_PID, facility=syslog.LOG_MAIL)
        try:
            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(config['fromemail'], 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)
            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 #49
0
    def send_vacation(self, email, destination):
        """
        Sends a vacation message to the destination address unless they have
        already been notified.

        :param user: The email of the user to send the message for
        :type user: str
        :param destination: The email address of the remote address
        :type destination: str
        """
        log.debug('Attempting to send vacation message to %s from %s',
                  destination, email)

        with self.db_session() as session:
            user = session.query(User).filter_by(email=email).first()
            if not user:
                raise UserNotFoundError(email)

            if not user.vacation:
                log.debug('User has no vacation message')
                return False

            if not user.vacation.active:
                log.debug('Vacation message is not active')
                return False

            try:
                recipient = Address.parse(destination)
            except Exception:
                return False

            # TODO: Add support for html vacation messages
            # Build up the response message here
            message = MIMEMessage()
            message.add_header('From', '%s <%s>' % (user.name, user.email))
            message.add_header('To', str(recipient))
            message.add_header('Date', formatdate())
            message.add_header('Subject', user.vacation.subject)
            message.set_payload(user.vacation.body.encode('utf8'))

            # Send the message to the local SMTP server
            smtp = smtplib.SMTP('localhost')
            try:
                log.debug("Sending vacation notification to '%s' for '%s'",
                          recipient.address, user.email)
                smtp.sendmail(user.email, recipient.address, str(message))
            except smtplib.SMTPRecipientsRefused:
                log.debug(
                    "Failed sending vacation notification to '%s' for '%s'",
                    recipient.address, user.email)
            finally:
                smtp.close()

            # Store that the recipient has been notified so we don't spam them
            # with useless information.
            notification = VacationNotification()
            notification.on_vacation = user.email
            notification.notified = destination
            notification.notified_at = datetime.datetime.now()
            session.add(notification)

            # FIXME: This is a kludgy fix to prevent unrequired error messages
            # when a vacation message is attempted to be sent to the same person
            # more than once. This should be resolved properly by allowing
            # configurable notification intervals and modifying the database
            # accordingly.
            try:
                session.commit()
            except IntegrityError:
                session.rollback()

            return True
env = load_environment()

# Process command line args.
subject = sys.argv[1]

# Administrator's email address.
admin_addr = "administrator@" + env['PRIMARY_HOSTNAME']

# Read in STDIN.
content = sys.stdin.read().strip()

# If there's nothing coming in, just exit.
if content == "":
    sys.exit(0)

# create MIME message
msg = Message()
msg['From'] = "\"%s\" <%s>" % (env['PRIMARY_HOSTNAME'], admin_addr)
msg['To'] = admin_addr
msg['Subject'] = "[%s] %s" % (env['PRIMARY_HOSTNAME'], subject)
msg.set_payload(content, "UTF-8")

# send
smtpclient = smtplib.SMTP('127.0.0.1', 25)
smtpclient.ehlo()
smtpclient.sendmail(
    admin_addr,  # MAIL FROM
    admin_addr,  # RCPT TO
    msg.as_string())
smtpclient.quit()
    def prepare_multipart_body(self, content_index=0):
        # type: (int) -> int
        """Will prepare the body of this request according to the multipart information.

        This call assumes the on_request policies have been applied already in their
        correct context (sync/async)

        Does nothing if "set_multipart_mixed" was never called.

        :param int content_index: The current index of parts within the batch message.
        :returns: The updated index after all parts in this request have been added.
        :rtype: int
        """
        if not self.multipart_mixed_info:
            return 0

        requests = self.multipart_mixed_info[0]  # type: List[HttpRequest]
        boundary = self.multipart_mixed_info[2]  # type: Optional[str]

        # Update the main request with the body
        main_message = Message()
        main_message.add_header("Content-Type", "multipart/mixed")
        if boundary:
            main_message.set_boundary(boundary)

        for req in requests:
            part_message = Message()
            if req.multipart_mixed_info:
                content_index = req.prepare_multipart_body(
                    content_index=content_index)
                part_message.add_header("Content-Type",
                                        req.headers['Content-Type'])
                payload = req.serialize()
                # We need to remove the ~HTTP/1.1 prefix along with the added content-length
                payload = payload[payload.index(b'--'):]
            else:
                part_message.add_header("Content-Type", "application/http")
                part_message.add_header("Content-Transfer-Encoding", "binary")
                part_message.add_header("Content-ID", str(content_index))
                payload = req.serialize()
                content_index += 1
            part_message.set_payload(payload)
            main_message.attach(part_message)

        try:
            from email.policy import HTTP

            full_message = main_message.as_bytes(policy=HTTP)
            eol = b"\r\n"
        except ImportError:  # Python 2.7
            # Right now we decide to not support Python 2.7 on serialization, since
            # it doesn't serialize a valid HTTP request (and our main scenario Storage refuses it)
            raise NotImplementedError(
                "Multipart request are not supported on Python 2.7")
            # full_message = main_message.as_string()
            # eol = b'\n'
        _, _, body = full_message.split(eol, 2)
        self.set_bytes_body(body)
        self.headers["Content-Type"] = ("multipart/mixed; boundary=" +
                                        main_message.get_boundary())
        return content_index
Example #52
0
    def do_test_sendToInterestedUsers(self,
                                      lookup=None,
                                      extraRecipients=[],
                                      sendToInterestedUsers=True,
                                      exp_called_with=None,
                                      exp_TO=None,
                                      exp_CC=None):
        from email.message import Message
        m = Message()

        mn = MailNotifier(fromaddr='*****@*****.**',
                          lookup=lookup,
                          sendToInterestedUsers=sendToInterestedUsers,
                          extraRecipients=extraRecipients)
        mn.sendMessage = Mock()

        def fakeGetBuild(number):
            return build

        def fakeGetBuilder(buildername):
            if buildername == builder.name:
                return builder
            return None

        def fakeGetBuildRequests(self, bsid):
            return defer.succeed([{"buildername": "Builder", "brid": 1}])

        builder = Mock()
        builder.getBuild = fakeGetBuild
        builder.name = "Builder"

        build = FakeBuildStatus(name="build")
        build.result = FAILURE
        build.finished = True
        build.reason = "testReason"
        build.builder = builder

        def fakeCreateEmail(msgdict,
                            builderName,
                            title,
                            results,
                            builds=None,
                            patches=None,
                            logs=None):
            # only concerned with m['To'] and m['CC'], which are added in
            # _got_recipients later
            return defer.succeed(m)

        mn.createEmail = fakeCreateEmail

        self.db = fakedb.FakeDBConnector(self)
        self.db.insertTestData([
            fakedb.SourceStampSet(id=1099),
            fakedb.Buildset(id=99,
                            sourcestampsetid=1099,
                            results=SUCCESS,
                            reason="testReason"),
            fakedb.BuildRequest(id=11, buildsetid=99, buildername='Builder'),
            fakedb.Build(number=0, brid=11),
            fakedb.Change(changeid=9123),
            fakedb.ChangeUser(changeid=9123, uid=1),
            fakedb.User(uid=1, identifier="tdurden"),
            fakedb.UserInfo(uid=1, attr_type='svn', attr_data="tdurden"),
            fakedb.UserInfo(uid=1,
                            attr_type='email',
                            attr_data="*****@*****.**")
        ])

        # fake sourcestamp with relevant user bits
        ss = Mock(name="sourcestamp")
        fake_change = Mock(name="change")
        fake_change.number = 9123
        ss.changes = [fake_change]
        ss.patch, ss.addPatch = None, None

        def fakeGetSSlist():
            return [ss]

        build.getSourceStamps = fakeGetSSlist

        def _getInterestedUsers():
            # 'narrator' in this case is the owner, which tests the lookup
            return ["narrator"]

        build.getInterestedUsers = _getInterestedUsers

        def _getResponsibleUsers():
            return ["Big Bob <*****@*****.**>"]

        build.getResponsibleUsers = _getResponsibleUsers

        mn.master = self  # FIXME: Should be FakeMaster
        self.status = mn.master_status = mn.buildMessageDict = Mock()
        mn.master_status.getBuilder = fakeGetBuilder
        mn.buildMessageDict.return_value = {"body": "body", "type": "text"}

        mn.buildMessage(builder.name, [build], build.result)
        mn.sendMessage.assert_called_with(m, exp_called_with)
        self.assertEqual(m['To'], exp_TO)
        self.assertEqual(m['CC'], exp_CC)
Example #53
0
    def createEmail(self,
                    msgdict,
                    builderName,
                    title,
                    results,
                    builds=None,
                    patches=None,
                    logs=None):
        text = msgdict['body'].encode(ENCODING)
        type = msgdict['type']
        if 'subject' in msgdict:
            subject = msgdict['subject'].encode(ENCODING)
        else:
            subject = self.subject % {
                'result': Results[results],
                'projectName': title,
                'title': title,
                'builder': builderName,
            }

        assert '\n' not in subject, \
            "Subject cannot contain newlines"

        assert type in ('plain', 'html'), \
            "'%s' message type must be 'plain' or 'html'." % type

        if patches or logs:
            m = MIMEMultipart()
            m.attach(MIMEText(text, type, ENCODING))
        else:
            m = Message()
            m.set_payload(text, ENCODING)
            m.set_type("text/%s" % type)

        m['Date'] = formatdate(localtime=True)
        m['Subject'] = subject
        m['From'] = self.fromaddr
        # m['To'] is added later

        if patches:
            for (i, patch) in enumerate(patches):
                a = self.patch_to_attachment(patch, i)
                m.attach(a)
        if logs:
            for log in logs:
                name = "%s.%s" % (log.getStep().getName(), log.getName())
                if (self._shouldAttachLog(log.getName())
                        or self._shouldAttachLog(name)):
                    # Use distinct filenames for the e-mail summary
                    if self.buildSetSummary:
                        filename = "%s.%s.%s" % (
                            log.getStep().getBuild().getBuilder().getName(),
                            log.getStep().getName(), log.getName())
                    else:
                        filename = name

                    text = log.getText()
                    if not isinstance(text, unicode):
                        # guess at the encoding, and use replacement symbols
                        # for anything that's not in that encoding
                        text = text.decode(LOG_ENCODING, 'replace')
                    a = MIMEText(text.encode(ENCODING), _charset=ENCODING)
                    a.add_header('Content-Disposition',
                                 "attachment",
                                 filename=filename)
                    m.attach(a)

        #@todo: is there a better way to do this?
        # Add any extra headers that were requested, doing WithProperties
        # interpolation if only one build was given
        if self.extraHeaders:
            if len(builds) == 1:
                d = builds[0].render(self.extraHeaders)
            else:
                d = defer.succeed(self.extraHeaders)

            @d.addCallback
            def addExtraHeaders(extraHeaders):
                for k, v in extraHeaders.items():
                    if k in m:
                        twlog.msg("Warning: Got header " + k +
                                  " in self.extraHeaders "
                                  "but it already exists in the Message - "
                                  "not adding it.")
                    m[k] = v

            d.addCallback(lambda _: m)
            return d

        return defer.succeed(m)
Example #54
0
def limit_reached_alert(user, limit_type, limit, value):
    """
    Send out a notification when a limit is reached.

    :param user: The user who has hit the limit
    :type user: User
    :param limit_type: The type of limit that has been reached
    :type limit_type: str
    :param limit: The limit amount
    :type limit: int
    :param value: The number of messages sent
    :type value: int
    """

    name = get_config('alerts_name')
    faddr = get_config('alerts_from')
    taddr = get_config('alerts_to')

    message = MIMEMessage()
    message.add_header('From', '"%s" <%s>' % (name, faddr))
    if isinstance(taddr, list):
        message.add_header('To', ', '.join(taddr))
    else:
        message.add_header('To', taddr)
    message.add_header('Date', formatdate())
    message.add_header('Subject', 'User %s reached sending limit' % user.email)
    message.set_payload("""Hi,

The user has reached their %s limit of sending messages. They have sent %d
messages and have a limit of %d""" % (limit_type, value, limit))

    # Send the message to the local SMTP server
    smtp = smtplib.SMTP('localhost')
    smtp.sendmail(faddr, taddr, str(message))
    smtp.close()
Example #55
0
#!/usr/bin/env python3
# Foundations of Python Network Programming, Third Edition
# https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter12/pre-python-3.4/trad_gen_newhdrs.py
# Traditional Message Generation with Date and Message-ID

import email.utils
from email.message import Message

message = """Hello,

This is a test message from Chapter 12.  I hope you enjoy it!

-- Anonymous"""

msg = Message()
msg['To'] = '*****@*****.**'
msg['From'] = 'Test Sender <*****@*****.**>'
msg['Subject'] = 'Test Message, Chapter 12'
msg['Date'] = email.utils.formatdate(localtime=1)
msg['Message-ID'] = email.utils.make_msgid()
msg.set_payload(message)

print(msg.as_string())
Example #56
0
    def sendMessage(self,
                    From,
                    To,
                    Subj,
                    extrahdrs,
                    bodytext,
                    attaches,
                    saveMailSeparator=(('=' * 80) + 'PY\n'),
                    bodytextEncoding='us-ascii',
                    attachesEncodings=None):
        """
        formats and sends an e-mail.
        saves the sent e-mail if sent sucessfully.
        arguments:
        bodytext - text part of the e-mail (assumes it is already in desired
                                                encoding.)
        attaches - list of files to be attached
        extrahdrs - list of tuples to be added (Name, Value)
        """
        # body text encoding
        if fix_text_required(bodytextEncoding):
            if not isinstance(bodytext, str):
                bodytext = bodytext.decode(bodytextEncoding)
        else:
            if not isinstance(bodytext, bytes):
                bodytext = bodytext.encode(bodytextEncoding)

        # attachments
        if not attaches:
            msg = Message()
            msg.set_payload(bodytext, charset=bodytextEncoding)
        else:
            msg = MIMEMultipart()
            self.addAttachments(msg, bodytext, attaches, bodytextEncoding,
                                attachesEncodings)

        # e-mail header encoding
        hdrenc = mailconfig.headersEncodeTo or 'utf-8'
        Subj = self.encodeHeader(Subj, hdrenc)
        From = self.encodeAddrHeader(From, hdrenc)
        To = [self.encodeAddrHeader(T, hdrenc) for T in To]
        Tos = ', '.join(To)

        # attach header to message
        msg['From'] = From
        msg['To'] = Tos
        msg['Subj'] = Subj
        msg['Date'] = email.utils.formatdate()
        recip = To

        for (name, value) in extrahdrs:
            if value:
                if name.lower() not in ['cc', 'bcc']:
                    value = self.encodeHeader(value, hdrenc)
                    msg[name] = value
                else:
                    value = [self.encodeAddrHeader(V, hdrenc) for V in value]
                    recip += value
                    if name.lower() != 'bcc':
                        msg[name] = ', '.join(value)

        # remove duplicates
        recip = list(set(recip))

        fullText = msg.as_string()

        self.trace('Sending to...' + str(recip))
        self.trace(fullText[:self.tracesize])

        # smtp connection.
        server = smtplib.SMTP_SSL(self.smtpservername)
        self.getPassword()
        self.authenticateServer(server)

        try:
            failed = server.sendmail(From, recip, fullText)
        except Exception:
            server.close()
            raise
        else:
            server.quit()

        self.saveSentMessage(fullText, saveMailSeparator)

        if failed:

            class SomeAddrsFailed(Exception):
                pass

            raise SomeAddrsFailed('Failed addrs:%s\n' % failed)
        self.trace('Send exit')
Example #57
0
def message_is_binary(message: Message) -> bool:
    """
    Determine if a non-multipart message is of binary type.
    """
    return message.get_content_maintype() not in ('text', 'message')
Example #58
0
def copy(msg: Message) -> Message:
    """return a copy of message"""
    return email.message_from_bytes(msg.as_bytes())
Example #59
0
    def test_get_activities_fetch_extras(self):
        self.init()

        # Generate minimal fake responses for each request in the batch.
        #
        # Test with multiple activities to cover the bug described in
        # https://github.com/snarfed/bridgy/issues/22#issuecomment-56329848 :
        # util.CacheDict.get_multi() didn't originally handle generator args.
        batch = MIMEMultipart()
        for i, item in enumerate((COMMENT_GP, PLUSONER, RESHARER) * 2):
            msg = Message()
            msg.set_payload('HTTP/1.1 200 OK\n\r\n\r\n' +
                            json.dumps({'items': [item]}))
            msg['Content-ID'] = '<response-abc+%d>' % (i + 1)
            batch.attach(msg)

        # as_string() must be called before get_boundary() to generate the
        # boundaries between parts, but can't be called again, so we capture the
        # result.
        batch_str = batch.as_string()

        gpe_1 = ACTIVITY_GP_EXTRAS
        gpe_2 = copy.deepcopy(gpe_1)
        gpe_2['id'] = '002'
        http_seq = http.HttpMockSequence([
            ({
                'status': '200'
            }, json.dumps({'items': [gpe_1, gpe_2]})),
            ({
                'status':
                '200',
                'content-type':
                'multipart/mixed; boundary="%s"' % batch.get_boundary()
            }, batch_str),
            ({
                'status': '200'
            }, json.dumps({'items': [gpe_1, gpe_2]})),
        ])

        self.auth_entity.http = lambda: http_seq

        ase_1 = ACTIVITY_AS_EXTRAS
        ase_2 = copy.deepcopy(ase_1)
        ase_2['id'] = tag_uri('002')
        ase_2['object']['tags'][0]['id'] = tag_uri('002_liked_by_222')
        ase_2['object']['tags'][1]['id'] = tag_uri('002_shared_by_444')
        cache = util.CacheDict()
        self.assert_equals([ase_1, ase_2],
                           self.googleplus.get_activities(fetch_replies=True,
                                                          fetch_likes=True,
                                                          fetch_shares=True,
                                                          cache=cache))
        for id in '001', '002':
            for prefix in 'AGL ', 'AGS ':
                self.assertEquals(1, cache[prefix + id])

        # no new extras, so another request won't fill them in
        as_1 = copy.deepcopy(ACTIVITY_AS)
        for field in 'replies', 'plusoners', 'resharers':
            as_1['object'][field] = {'totalItems': 1}
        as_2 = copy.deepcopy(as_1)
        as_2['id'] = tag_uri('002')
        self.assert_equals([as_1, as_2],
                           self.googleplus.get_activities(fetch_replies=True,
                                                          fetch_likes=True,
                                                          fetch_shares=True,
                                                          cache=cache))
Example #60
0
        def test_readfile_operations(self):
            class ITest(Interface):
                title = schema.TextLine()
                body = schema.Text()

            alsoProvides(ITest['body'], IPrimaryField)

            fti_mock = DexterityFTI(u'testtype')
            fti_mock.lookupSchema = Mock(return_value=ITest)
            fti_mock.behaviors = [ITestBehavior.__identifier__]

            self.mock_utility(fti_mock, IDexterityFTI, name=u"testtype")

            item = Item('item')
            item.portal_type = 'testtype'

            readfile = DefaultReadFile(item)

            message = Message()
            message['title'] = 'Test title'
            message['foo'] = '10'
            message['bar'] = 'xyz'
            message.set_payload('<p>body</p>')

            from plone.rfc822 import constructMessageFromSchemata
            self.patch_global(constructMessageFromSchemata,
                              return_value=message)

            body = b"""\
title: Test title
foo: 10
bar: xyz
Portal-Type: testtype

<p>body</p>"""

            # iter
            # next

            self.assertEqual(body, readfile.read())
            self.assertEqual(69, readfile.size())
            self.assertEqual('utf-8', readfile.encoding)
            self.assertEqual(None, readfile.name)
            self.assertEqual('text/plain', readfile.mimeType)

            readfile.seek(2)
            self.assertEqual(2, readfile.tell())
            self.assertEqual(b'tl', readfile.read(2))
            self.assertEqual(4, readfile.tell())

            readfile.seek(0, 2)
            self.assertEqual(69, readfile.tell())

            readfile.seek(0)
            self.assertEqual(b'foo: 10\n', readfile.readlines()[1])

            readfile.seek(0)
            self.assertEqual(b'foo: 10\n', readfile.readlines(100)[1])

            readfile.seek(0)
            self.assertEqual(b'title: Test title\n', readfile.readline())

            readfile.seek(0)
            self.assertEqual(b'title: Test title\n', readfile.readline(100))

            readfile.seek(0)
            self.assertEqual(b'foo: 10\n', list(iter(readfile))[1])

            self.assertEqual(False, readfile.closed)
            readfile.close()