Example #1
0
def _plain_send_mail(sender, recipient, subject, body):
    header_charset = 'ISO-8859-1'
    for body_charset in 'US-ASCII', 'ISO-8859-1', 'UTF-8':
        try:
            body.encode(body_charset)
        except UnicodeError:
            pass
        else:
            break

    sender_name, sender_addr = parseaddr(sender)
    recipient_name, recipient_addr = parseaddr(recipient)

    sender_name = str(Header(unicode(sender_name), header_charset))
    recipient_name = str(Header(unicode(recipient_name), header_charset))

    sender_addr = sender_addr.encode('ascii')
    recipient_addr = recipient_addr.encode('ascii')

    msg = MIMEText(body.encode(body_charset), 'plain', body_charset)
    msg['From'] = formataddr((sender_name, sender_addr))
    msg['To'] = formataddr((recipient_name, recipient_addr))
    msg['Subject'] = Header(unicode(subject), header_charset)

    smtp = SMTP(config.get('registration.smtp_host', 'localhost'))
    if config.get('registration.smtp_login'):
        try:
            smtp.starttls()
        except:
            pass
        smtp.login(config.get('registration.smtp_login'), config.get('registration.smtp_passwd'))
    smtp.sendmail(sender, recipient, msg.as_string())
    smtp.quit()
    def handle_new_email_requests(self, num, raw_email):
        attmts = list()
        tmp_dict = dict()
        tmp_dict.update({'has_link': 'not set', 'link': None, 'object': None,
                         'search_link': "https://fsinvestments.my.salesforce.com"})
        tmp_dict['name'], tmp_dict['email'] = parseaddr(raw_email['From'])[0], parseaddr(raw_email['From'])[1]
        tmp_dict['sub'] = raw_email['subject']

        try:
            tmp_dict['date'] = datetime.datetime.strftime(
                date_parsing(raw_email['date']), '%m/%d/%Y %H:%M:%S')
        except ValueError:
            test_date = ' '.join(raw_email['date'].split(' ')[:-1])
            tmp_dict['date'] = datetime.datetime.strftime(
                datetime.datetime.strptime(test_date, '%a, %d %b %Y %H:%M:%S %z'), '%m/%d/%Y %H:%M:%S')

        msg_body = "Sent by: %s\nReceived on: %s\nSubject: %s\n" % (tmp_dict['name'], tmp_dict['date'], tmp_dict['sub'])
        for part in raw_email.walk():
            if part.get_content_type().lower() == "text/html" and tmp_dict['has_link'] == 'not set':
                e_body = fromstring(part.get_payload(decode=True)).text_content()
                e_body = e_body[e_body.find("-->") + 3:]
                tmp_dict['has_link'] = e_body.find(tmp_dict['search_link'])
                if tmp_dict['has_link'] not in ['not set', -1]:
                    tmp_dict = determine_id_and_object_from_link(tmp=tmp_dict, email_text=e_body, log=self.log)
                msg_body += re.sub(r'[^\x00-\x7F]+', ' ', e_body)

            if part.get_content_maintype() == "mulipart": continue
            if part.get("Content-Disposition") is None: continue
            if part.get_filename() is not None:
                attmts.append(attachment_reader(raw=part, att=part.get_filename()))
        self.determine_path_and_complete_processing(num=num, dict_data=tmp_dict, att=attmts, msg_body=msg_body,
                                                    sender_addr=tmp_dict['email'])
        attachment_reader(remove=True)
    def modify_header(self, email):
        '''Generate the content for the :mailheader:`Reply-To` header

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

    * The email address from the :mailheader:`From` header if the
      ``replyto`` property of the list-object is set to ``sender``. This is
      the default for announcement groups, as few group members can post to
      the group.
    * Both the email-address in the :mailheader:`From` header and the
      email-address of the group if the ``replyto`` property of the
      list-object is set to ``both``. (Yes, the :mailheader:`Reply-To`
      header can contain an *address-list* according to
      :rfc:`5322#section-3.6.2`.)
    * The email address for the group in all other cases. This is the
      default for most groups.

:rtype: bytes'''
        authorReplyTo = parseaddr(email.get('Reply-To',
                                  email.get('From')))[1]
        groupReplyTo = parseaddr(self.listInfo.get_property('mailto'))[1]
        replyTo = replyto(self.listInfo)
        if replyTo == ReplyTo.author:
            retval = authorReplyTo
        elif replyTo == ReplyTo.both:
            addrs = [a for a in [authorReplyTo, groupReplyTo] if a]
            retval = ', '.join(addrs)
        else:  # ReplyTo.group
            retval = groupReplyTo
        return retval
Example #4
0
def convert_email_object_to_dict(email):
    """Converts a gmail.Email object into a dict to make it picklable"""
    return dict(subject=email.subject,
                fr=parseaddr(email.fr),
                to=parseaddr(email.to),
                sent_at=email.sent_at,
               )
Example #5
0
    def send_html_email(self, to_, from_=None, subject=None, text=None,
                        html=None, charset="utf-8"):

        message = MIMEMultipart("alternative")

        if subject:
            subject_header = Header()
            subject = (codecs.decode(bytearray(subject, sys.getdefaultencoding()), charset)
                       if isinstance(subject, str) else subject)
            subject_header.append(subject.strip())
            message["Subject"] = subject_header

        from_ = from_ or self.default_sender
        from_ = (codecs.decode(bytearray(from_, sys.getdefaultencoding()), charset)
                 if isinstance(from_, str) else from_)
        from_realname, from_addr = parseaddr(from_)
        from_header = Header()
        from_header.append(formataddr((from_realname, from_addr)))
        message['From'] = from_header

        to_ = (codecs.decode(bytearray(to_, sys.getdefaultencoding()), charset)
               if isinstance(to_, str) else to_)
        to_realname, to_addr = parseaddr(to_)
        to_header = Header()
        to_header.append(formataddr((to_realname, to_addr)))
        message['To'] = to_header

        message.attach(MIMEText(text, "plain", charset))
        message.attach(MIMEText(html, "html", charset))

        self._send(message, from_addr, to_addr)
Example #6
0
def get_cc(doc, recipients=None, fetched_from_email_account=False):
	"""Build a list of email addresses for CC"""
	# get a copy of CC list
	cc = split_emails(doc.cc)

	if doc.reference_doctype and doc.reference_name:
		if fetched_from_email_account:
			# if it is a fetched email, add follows to CC
			cc.append(get_owner_email(doc))
			cc += get_assignees(doc)

	if getattr(doc, "send_me_a_copy", False) and doc.sender not in cc:
		cc.append(doc.sender)

	if cc:
		# exclude email accounts, unfollows, recipients and unsubscribes
		exclude = [d[0] for d in
			frappe.db.get_all("Email Account", ["email_id"], {"enable_incoming": 1}, as_list=True)]
		exclude += [d[0] for d in
			frappe.db.get_all("Email Account", ["login_id"], {"enable_incoming": 1}, as_list=True)
			if d[0]]
		exclude += [d[0] for d in frappe.db.get_all("User", ["name"], {"thread_notify": 0}, as_list=True)]
		exclude += [(parseaddr(email)[1] or "").lower() for email in recipients]

		if fetched_from_email_account:
			# exclude sender when pulling email
			exclude += [parseaddr(doc.sender)[1]]

		if doc.reference_doctype and doc.reference_name:
			exclude += [d[0] for d in frappe.db.get_all("Email Unsubscribe", ["email"],
				{"reference_doctype": doc.reference_doctype, "reference_name": doc.reference_name}, as_list=True)]

		cc = filter_email_list(doc, cc, exclude, is_cc=True)

	return cc
Example #7
0
 def __init__(self, name_or_email, email=None, encoding='utf-8'):
     if email is None:
         if isinstance(name_or_email, AddressList):
             if not 0 < len(name_or_email) < 2:
                 raise ValueError("AddressList to convert must only contain a single Address.")
             
             name_or_email = unicode(name_or_email[0])
         
         if isinstance(name_or_email, (tuple, list)):
             self.name = unicodestr(name_or_email[0], encoding)
             self.address = unicodestr(name_or_email[1], encoding)
         
         elif isinstance(name_or_email, bytes):
             self.name, self.address = parseaddr(unicodestr(name_or_email, encoding))
         
         elif isinstance(name_or_email, unicode):
             self.name, self.address = parseaddr(name_or_email)
         
         else:
             raise TypeError('Expected string, tuple or list, got {0} instead'.format(
                     repr(type(name_or_email))
                 ))
     else:
         self.name = unicodestr(name_or_email, encoding)
         self.address = unicodestr(email, encoding)
     
     email, err = EmailValidator().validate_email(self.address)
     
     if err:
         raise ValueError('"{0}" is not a valid e-mail address: {1}'.format(email, err))
Example #8
0
    def __init__(self, raw_email):
        metadata = raw_email[0].replace('(', '').split()

        # X-GM-MSGID as _id
        self['_created'] = datetime.now()

        self['X-GM-THRID'] = int(metadata[2])
        self['X-GM-MSGID'] = int(metadata[4])
        self['UID'] = int(metadata[6])

        msg = email.message_from_string(raw_email[1])

        self['Message-ID'] = msg.get('Message-ID')
        if msg.has_key('In-Reply-To'):
            self['In-Reply-To'] = msg.get_all('In-Reply-To')
        if msg.has_key('References'):
            self['References'] = msg.get('References').split('\r\n ')
        if msg.has_key('List-ID'):
            self['List-ID'] = msg.get('List-ID')

        self['From'] = utils.parseaddr(msg.get('From'))[1]

        if msg.has_key('To'):
            self['To'] = map(lambda x: utils.parseaddr(x)[1], msg.get_all('To'))
        if msg.has_key('Cc'):
            self['Cc'] = map(lambda x: utils.parseaddr(x)[1], msg.get_all('Cc'))

        self['Date'] = self._convert_string_to_date(msg.get('Date'))
        self['Subject'] = self._decode_text(msg.get('Subject'), msg)
        self['Body'] = self._get_body_from_email(msg)
Example #9
0
def incoming_email(request, file_key):
    logging.info('processing incoming email %s'%file_key)

    data = get_blob_data(file_key)
    if data is None:
        raise Http404

    logging.info('email fetch ok')
    email = EmailMessage(data)
    a_to = parseaddr(email.to)[1]
    a_from = parseaddr(email.sender)[1]
    logging.info('email.to=%s'%a_to) 
    logging.info('email.sender=%s'%a_from) 

    if re.match(r'^import-order@',a_to):
        logging.info('import order')
        process_incoming_email_order(email)
        return HttpResponse("ok - import order")

    if a_from == '*****@*****.**':
        logging.info('import order')
        process_incoming_email_order(email)
        return HttpResponse("ok - import order")


    r = re.match(r'^import-email-(\d+)@',a_to) 
    if r:
        logging.info('import email, id %s'%r.group(1))
        process_incoming_email_template(r.group(1),data)
        return HttpResponse("ok - import email")
        

    return HttpResponse("ok -ign") 
Example #10
0
def test_to_message_from_message_with_spam():
    mb = mailbox.mbox("tests/spam")
    fails = 0
    total = 0

    for msg in mb:
        try:
            m = encoding.from_message(msg)
            out = encoding.to_message(m)
            assert repr(out)

            m2 = encoding.from_message(out)

            for k in m:
                if '@' in m[k]:
                    assert_equal(parseaddr(m[k]), parseaddr(m2[k]))
                else:
                    assert m[k].strip() == m2[k].strip(), "%s: %r != %r" % (k, m[k], m2[k])

                assert not m[k].startswith(u"=?")
                assert not m2[k].startswith(u"=?")
                assert m.body == m2.body, "Bodies don't match" 

                assert_equal(len(m.parts), len(m2.parts), "Not the same number of parts.")

                for i, part in enumerate(m.parts):
                    assert part.body == m2.parts[i].body, "Part %d isn't the same: %r \nvs\n. %r" % (i, part.body, m2.parts[i].body)
            total += 1
        except encoding.EncodingError, exc:
            fails += 1
Example #11
0
def send_single_email(sender, recipient, subject, text, html=None, category=None):
    sender_name, sender_addr = parseaddr(sender)
    from_addr = formataddr((Header(sender_name, CHARSET_UTF8).encode(), sender_addr))
    recipient_name, recipient_addr = parseaddr(recipient)
    to_addr = formataddr((Header(recipient_name, CHARSET_UTF8).encode(), recipient_addr))

    msg = MIMEMultipart('alternative')
    msg['From'] = from_addr
    msg['To'] = to_addr
    msg['Subject'] = subject
    if category:
        msg["X-SMTPAPI"] = '{"category" : "%s"}' % category
    part1 = MIMEText(text, 'plain', CHARSET_UTF8)
    msg.attach(part1)
    if html:
        part2 = MIMEText(html, 'html', CHARSET_UTF8)
        msg.attach(part2)
    cfg = config()
    username = cfg.get('email', 'username')
    password = cfg.get('email', 'password')
    log.info('Sending email to recipient: {}'.format(recipient))
    s = smtplib.SMTP(cfg.get('email', 'sp_address'), port=cfg.get('email', 'sp_port'))
    s.login(username, password)
    s.sendmail(from_addr, to_addr, msg.as_string())
    s.quit()
Example #12
0
    def send_messages(self, email_messages, **kwargs):
        ''' Django Email Backend API - send_messages

            :param email_messages:
                list of django.core.mail.messages.EmailMessage instance

            - https://github.com/django
              /django/blob/master/django/core/mail/message.py

        .. todo::
            - DO ERROR CHECK!!!!
            - DO ERROR TRACE!!!!
        '''
        logger.debug(_('JournalEmailBackend is used to send a message.'))
        from tasks import journalize
        try:
            sender = parseaddr(email_messages[0].from_email)[1]
            recipient = parseaddr(email_messages[0].to[0])[1]
            journalize(sender, recipient,
                       email_messages[0].message().as_string(), True)
            return 1
        except Exception:
            for err in traceback.format_exc().split('\n'):
                logger.error(err)
            return 0
Example #13
0
def test_gzip_attachment():

    clear_queue()
    
    # set up list and message
    name, address = parseaddr(gzip_msg['from'])
    client = RouterConversation(address, 'Files Tests')
    client.begin()
    mlist = mailinglist.find_list(list_name)
    test_subscribe_user(sender=address, client=client, mlist=mlist)
    
    test_subscribe_user(sender=parseaddr(sender)[1], client=sender_client, mlist=mlist)
    gzip_msg['to'] = list_addr

    # deliver the message.
    clear_queue()
    Router.deliver(gzip_msg)

    assert len(mlist.message_set.all()) == 1
    msg = mlist.message_set.all()[0]
    
    assert len(msg.file_set.all()) == 1
    attached = msg.file_set.all()[0]
    path = os.path.join(attached.pathprefix, attached.sha)
    assert attached.name in os.listdir(path)
    assert queue().count() == 1, "Should be 1 message in queue, but there are %s" % queue().count()
Example #14
0
 def from_email(self, emails):
     for addr in emails:
         addr = parseaddr(addr)[1].lower()
         for my in self.from_emails:
             if parseaddr(my)[1].lower() == addr:
                 return my
     return None
Example #15
0
    def send_email(self, to_, from_=None, subject=None, body=None,
                   subtype="plain", charset="utf-8"):

        message = MIMEText(body, subtype, charset)

        if subject:
            subject_header = Header()
            subject = (codecs.decode(bytearray(subject, sys.getdefaultencoding()), charset)
                       if isinstance(subject, str) else subject)
            subject_header.append(subject.strip())
            message["Subject"] = subject_header

        from_ = from_ or self.default_sender
        from_ = (codecs.decode(bytearray(from_, sys.getdefaultencoding()), charset)
                 if isinstance(from_, str) else from_)
        from_realname, from_addr = parseaddr(from_)
        from_header = Header()
        from_header.append(formataddr((from_realname, from_addr)))
        message['From'] = from_header

        to_ = (codecs.decode(bytearray(to_, sys.getdefaultencoding()), charset)
               if isinstance(to_, str) else to_)
        to_realname, to_addr = parseaddr(to_)
        to_header = Header()
        to_header.append(formataddr((to_realname, to_addr)))
        message['To'] = to_header

        self._send(message, from_addr, to_addr)
Example #16
0
	def get_recipients(self, except_recipient=False):
		"""Build a list of users to which this email should go to"""
		original_recipients = [s.strip() for s in self.recipients.split(",")]
		recipients = original_recipients[:]

		if self.reference_doctype and self.reference_name:
			recipients += self.get_earlier_participants()
			recipients += self.get_commentors()
			recipients += self.get_assignees()
			recipients += self.get_starrers()

		# remove unsubscribed recipients
		unsubscribed = [d[0] for d in frappe.db.get_all("User", ["name"], {"thread_notify": 0}, as_list=True)]
		email_accounts = [d[0] for d in frappe.db.get_all("Email Account", ["email_id"], {"enable_incoming": 1}, as_list=True)]
		sender = parseaddr(self.sender)[1]

		filtered = []
		for e in list(set(recipients)):
			if (e=="Administrator") or ((e==self.sender) and (e not in original_recipients)) or \
				(e in unsubscribed) or (e in email_accounts):
				continue

			email_id = parseaddr(e)[1]
			if email_id==sender or email_id in unsubscribed or email_id in email_accounts:
				continue

			if except_recipient and (e==self.recipients or email_id==self.recipients):
				# while pulling email, don't send email to current recipient
				continue

			if e not in filtered and email_id not in filtered:
				filtered.append(e)

		return filtered
    def post(self, request):
        token = request.POST['token']
        signature = request.POST['signature']
        timestamp = request.POST['timestamp']

        key = options.get('mail.mailgun-api-key')
        if not key:
            logging.error('mail.mailgun-api-key is not set')
            return HttpResponse(status=500)

        if not self.verify(key, token, timestamp, signature):
            logging.info('Unable to verify signature for mailgun request')
            return HttpResponse(status=403)

        to_email = parseaddr(request.POST['To'])[1]
        from_email = parseaddr(request.POST['From'])[1]

        try:
            group_id = email_to_group_id(to_email)
        except Exception:
            logging.info('%r is not a valid email address', to_email)
            return HttpResponse(status=500)

        payload = EmailReplyParser.parse_reply(request.POST['body-plain']).strip()
        if not payload:
            # If there's no body, we don't need to go any further
            return HttpResponse(status=200)

        process_inbound_email.delay(from_email, group_id, payload)

        return HttpResponse(status=201)
Example #18
0
 def create_mail_document(self,mail):
     body = ""
     if(mail.is_multipart()):
         body = self.get_body_from_multipart_mail(mail)
     else:
         body = unicode(mail.get_payload(decode=True),self.get_charset(mail),"replace")
     from_email = parseaddr(mail.get('From'))[1]
     if(mail.get_all('Cc')):
         ccs_string = mail.get_all('Cc')
     else:
         ccs_string = ''
     if(mail.get_all('To')):
         tos_string = mail.get_all('To')
     else:
         tos_string = ''
     cc_emails = map(lambda addr:addr[1],getaddresses(ccs_string))
     to_emails = map(lambda addr:addr[1],getaddresses(tos_string))
     from_user = parseaddr(mail.get('From'))[0]
     subject = mail.get('Subject')
     message_id = mail.get('Message-Id')
     date = datetime.fromtimestamp(mktime(parsedate(mail.get('Date'))))
     body = Mail.clean_body(body)
     from_user = self.get_user_name(from_user,from_email)
     sender ,creation_status = User.objects.get_or_create(email=from_email,auto_save=False)
     if creation_status:
         sender.name = from_user
         sender.save()
     mail_document = Mail(message_id=message_id,body=body,to=to_emails,sender=sender,cc=cc_emails,subject=subject,date=date)
     return mail_document
Example #19
0
def send(debug, header, To, Content, filenames=None):

    header['From'] = formataddr(parseaddr(header['From']))
    To = formataddr(parseaddr(To))

    if filenames:
        msg = multipart.MIMEMultipart()
        # a header mezőit átmásoljuk az üzenetbe
        for field in header:
            msg[field] = header[field]
        msg['To'] = To

        body = text.MIMEText(Content, 'plain', 'utf-8')
        msg.attach(body)

        for filename in filenames:
            msg.attach(attach(filename))

    # Csatolás nélküli szimpla email
    else:
        msg = text.MIMEText(Content, 'plain', 'utf-8')
        for field in header:
            msg[field] = header[field]
        msg['To'] = To

    # Ha csak debug kell, akkor elmentjük a "debug" változóba
    if debug:
        open(debug, 'a').write('From pistike Mon Jan 01 00:00:00 2000\n' + msg.as_string() + '\n')
    # egyébként elküldjük
    else:
        s = smtplib.SMTP('localhost')
        s.sendmail(header['From'], [To], msg.as_string())
        s.quit()
Example #20
0
    def _build_standard_message_dict(self, message):
        """Create a Mandrill send message struct from a Django EmailMessage.

        Builds the standard dict that Django's send_mail and send_mass_mail
        use by default. Standard text email messages sent through Django will
        still work through Mandrill.

        Raises ValueError for any standard EmailMessage features that cannot be
        accurately communicated to Mandrill (e.g., prohibited headers).
        """
        sender = sanitize_address(message.from_email, message.encoding)
        from_name, from_email = parseaddr(sender)

        recipients = [parseaddr(sanitize_address(addr, message.encoding))
                      for addr in message.recipients()]
        to_list = [{"email": to_email, "name": to_name}
                   for (to_name, to_email) in recipients]

        msg_dict = {
            "text": message.body,
            "subject": message.subject,
            "from_email": from_email,
            "to": to_list
        }
        if from_name:
            msg_dict["from_name"] = from_name

        if message.extra_headers:
            for k in message.extra_headers.keys():
                if k != "Reply-To" and not k.startswith("X-"):
                    raise ValueError("Invalid message header '%s' - Mandrill "
                                     "only allows Reply-To and X-* headers" % k)
            msg_dict["headers"] = message.extra_headers

        return msg_dict
Example #21
0
def generate_name(msg, folder_path):
    mailtm = msg.get('Date')
    messageid = msg.get('Message-Id')
    subject = msg.get('Subject')
    from_email = msg.get('From')
    path = [folder_path]
    flag = 0
    flag = check_from_subject(from_email, subject)  #检查邮件的类型:0 正常,1 错误,2 垃圾
    if flag: #根据邮件的类型,来分开存放
        path.append(mailtype[flag])
    mailtime = time.localtime(handle_time(mailtm))
    m = hashlib.md5()
    m.update(msg.get('message-id', 'none'))
    m.update(msg.get('From', 'none'))
    m.update(msg.get('Subject', 'None'))
    inbox_time = time.strftime('%Y-%m-%d %H:%M:%S', mailtime)
    if '@' in utils.parseaddr(msg.get('From'))[1]:
        fle_name = time.strftime("%d-%H%M%S-",mailtime) + m.hexdigest()+"-"+ utils.parseaddr(msg.get('From'))[1]+".eml"
    else:
        fle_name = time.strftime("%d-%H%M%S-",mailtime) + m.hexdigest()+".eml"
    folder = time.strftime('%Y%m', mailtime)
    path.append(folder)
    if not os.path.exists('/'.join(path)):
        os.makedirs('/'.join(path))
    path.append(fle_name)
    return (flag, inbox_time, '/'.join(path), m.hexdigest())
Example #22
0
    def testEmailParsing(self):
        # create an initial "from" email
        message = email.message_from_file(
            open("./testdata/mail3.txt", "r"))
        name, mto = parseaddr(message['to'])
        name, mfrom = parseaddr(message['from'])
        for part in message.walk():
            if part.get_content_maintype() == "multipart":
                continue # it's just a container
            if part.get_content_type() == "text/plain":
                body = part.get_payload(decode=True)
                break
        try:
            user = CustomUser.objects.get(
                email=mfrom)
        except CustomUser.DoesNotExist:
            user = CustomUser.objects.create(email=mfrom,
                                             username=mfrom)
            user.set_unusable_password()
            user.save()
        recipient, _ = CustomUser.objects.get_or_create(
            email=mto,
            username=mto)
        mail = Mail.objects.create(
            subject=message['subject'],
            mfrom=user,
            mto=recipient,
            message=body)

        # now we simulate a reply, and override a couple of relevant
        # headers 
        raw_email = email.message_from_file(
            open("./testdata/mail4.txt", "r"))
        new_mto = user.proxy_email
        raw_email.replace_header('in-reply-to', "<%s>" % mail.message_id)
        raw_email.replace_header('references', "<%s>" % mail.message_id)
        raw_email.replace_header('to', "%s <%s>" % (mail.message_id,
                                      new_mto))
        fp = StringIO(raw_email.as_string()) 
        response = make_response_from_file(fp)
        self.assertTrue(response)
        
        # now parse in an email that isn't a response to anything
        fp = open("./testdata/mail2.txt", "r")
        response = make_response_from_file(fp)
        self.assertEqual(response, EX_NOUSER)

        # and now try threading based on subject line as a fallback...
        raw_email = email.message_from_file(
            open("./testdata/mail2.txt", "r"))
        new_mto = user.proxy_email
        del(raw_email['in-reply-to'])
        del(raw_email['references'])
        raw_email.replace_header('subject', "Re:RE: re:%s" % mail.subject)
        raw_email.replace_header('to', "%s <%s>" % (mail.message_id,
                                      new_mto))
        fp = StringIO(raw_email.as_string()) 
        response = make_response_from_file(fp)
        self.assertTrue(response)
Example #23
0
    def send_email(self, sender, recipient, subject, body):
        """
        Send an email
        :param sender: the senders address
        :param recipient: the recipients address
        :param subject: the emails subject
        :param body: the body of the email
        :return: nothing
        """
        # Header class is smart enough to try US-ASCII, then the charset we
        # provide, then fall back to UTF-8.
        header_charset = 'ISO-8859-1'

        # We must choose the body charset manually
        body_charset = None
        for body_charset in 'US-ASCII', 'ISO-8859-1', 'UTF-8':
            try:
                body.encode(body_charset)
            except UnicodeError:
                pass
            else:
                break

        if body_charset is None:
            log.error("Can not encode body of an email")
            raise Exception("Email body encoding problem for email with subject{}".format(subject))

        # Split real name (which is optional) and email address parts
        sender_name, sender_addr = parseaddr(sender)
        recipient_name, recipient_addr = parseaddr(recipient)

        # We must always pass Unicode strings to Header, otherwise it will
        # use RFC 2047 encoding even on plain ASCII strings.
        sender_name = str(Header(unicode(sender_name), header_charset))
        recipient_name = str(Header(unicode(recipient_name), header_charset))

        # Make sure email addresses do not contain non-ASCII characters
        sender_addr = sender_addr.encode('ascii')
        recipient_addr = recipient_addr.encode('ascii')

        # Create the message ('plain' stands for Content-Type: text/plain)
        msg = MIMEText(body.encode(body_charset), 'plain', body_charset)
        msg['From'] = formataddr((sender_name, sender_addr))
        msg['To'] = formataddr((recipient_name, recipient_addr))
        msg['Subject'] = Header(unicode(subject), header_charset)

        try:
            # Send the message via SMTP to localhost:25
            smtp = SMTP(self._config['email.smtp_server'], port=self._config['email.smtp_port'], timeout=1)
            smtp.sendmail(sender, recipient, msg.as_string())
            smtp.quit()
        except KeyError:
            log.warn("There is no smtp server set in the config file.")
        except timeout:
            log.error("There is smtp timeout error message not sent.")
            log.error("Message was %s" % str(msg))
        except SMTPException, ex:
            log.error("There is smtp error. Message not sent: %s." % str(ex))
            log.error("Message was %s" % str(msg))
Example #24
0
def parse(content):
    p = EmailParser()
    msgobj = p.parsestr(content)
    if msgobj['Subject'] is not None:
        decodefrag = decode_header(msgobj['Subject'])
        subj_fragments = []
        for s, enc in decodefrag:
            if enc:
                s = unicode(s , enc).encode('utf8', 'replace')
            subj_fragments.append(s)
        subject = ''.join(subj_fragments)
    else:
        subject = None

    attachments = []
    body = None
    html = None
    images = []
    images_content_type = [
        "image/jpg",
        "image/jpeg",
        "image/png",
        "image/tiff"
        "application/pdf",
    ]

    for part in msgobj.walk():
        print part.get_content_type()
        attachment = parse_attachment(part)
        if attachment:
            attachments.append(attachment)
        elif part.get_content_type() == "text/plain":
            if body is None:
                body = ""
            body += unicode(
                part.get_payload(decode=True),
                part.get_content_charset(),
                'replace'
            ).encode('utf8', 'replace')
        elif part.get_content_type() == "text/html":
            if html is None:
                html = ""
            html += unicode(
                part.get_payload(decode=True),
                part.get_content_charset(),
                'replace'
            ).encode('utf8', 'replace')
        elif part.get_content_type() in images_content_type:
            images.append(StringIO(part.get_payload(decode=True)))

    return {
        'subject': subject,
        'body': body,
        'html': html,
        'from': parseaddr(msgobj.get('From'))[1],
        'to': parseaddr(msgobj.get('To'))[1],
        'attachments': attachments,
        'images': images,
    }
Example #25
0
def parse(content):
    #p = EmailParser()
    #msgobj = p.parse(content)
    msgobj = content
    messagedate = parser.parse(msgobj['Date'])
    if msgobj['Subject'] is not None:
        decodefrag = decode_header(msgobj['Subject'])
        subj_fragments = []
        for s , enc in decodefrag:
            if enc:
                try:
                    s = unicode(s , enc).encode('utf8','replace')
                except:
                    print "CANNOT DECODE"

            subj_fragments.append(s)
        subject = ''.join(subj_fragments)
    else:
        subject = None

    attachments = []
    body = None
    html = None
    for part in msgobj.walk():
        attachment = None#parse_attachment(part)
        if attachment:
            attachments.append(attachment)
        elif part.get_content_type() == "text/plain":
            try:
                if body is None:
                    body = ""
                body += unicode(
                    part.get_payload(decode=True),
                    "Latin-1" if part.get_content_charset() is None else part.get_content_charset(),
                    'replace'
                ).encode('utf8','replace')
            except:
                print "CANNOT DECODE"
        elif part.get_content_type() == "text/html":
            try:
                if html is None:
                    html = ""
                html += unicode(
                    part.get_payload(decode=True),
                    "Latin-1" if part.get_content_charset() is None else part.get_content_charset(),
                    'replace'
                ).encode('utf8','replace')
            except:
                print "CANNOT DECODE"
    return {
        'date' : messagedate,
        'subject' : subject,
        'body' : body,
        'html' : html,
        'from' : parseaddr(msgobj.get('From'))[1],
        'to' : parseaddr(msgobj.get('To'))[1],
        'attachments': attachments,
    }
Example #26
0
def fetch_and_store():
    detach_dir = '.'
    m = imaplib.IMAP4_SSL("imap.gmail.com")
    m.login('*****@*****.**',getPassword())
    m.select("inbox")

    resp, items = m.search(None, "(UNSEEN)")
    items = items[0].split()

    for emailid in items:
        resp, data = m.fetch(emailid, "(RFC822)")
        email_body = data[0][1]
        resp2, header = m.fetch(emailid, '(BODY[HEADER.FIELDS (SUBJECT)])')
        subject = header[0][1]
        parser = HeaderParser()
        msg = parser.parsestr(subject)
        subjectline = "".join(re.findall(r'[0-9a-zA-Z\-]', msg["Subject"]))

        mail = email.message_from_string(email_body)
        from email.utils import parseaddr
        fromaddr = parseaddr(mail['from'])[1]
        name = parseaddr(mail['from'])[0]
        temp = m.store(emailid,'+FLAGS', '\\Seen')
        m.expunge()
        sender = checkSender(fromaddr)
        if not parseSubLine(subjectline) or not sender :             #Ifall mailet har fel rubrik, går vi in här
            if not parseSubLine(subjectline) :
                print "Warning: Mail has wrong subject"
                sendEmail(name, fromaddr, subjectline, "2")     #Skickar ett mail till avsändaren om att dess mail haft fel format på rubriken
            elif not sender :
                print "Warning: Address not in senders file"
                sendEmail(name, fromaddr, subjectline, "1")     #Skickar ett mail till avsändaren om adressen inte finns i "sender.txt"-listan
        else:
            if not os.path.exists(subjectline):
                os.makedirs(subjectline)

            if mail.get_content_maintype() != 'multipart':
                continue

            filenamelist = []
            for part in mail.walk():

                if part.get_content_maintype() == 'multipart':
                    continue
                if part.get('Content-Disposition') is None:
                    continue

                filename = "".join(re.findall(r'[.0-9a-zA-Z\-]',part.get_filename()))
                att_path = os.path.join(detach_dir + "/" + subjectline, filename)
                filenamelist.append(filename)
                if not os.path.isfile(att_path) :
                    fp = open(att_path, 'wb')
                    fp.write(part.get_payload(decode=True))
                    fp.close()
            course = sender[0]
            name = sender[1]
            dest = "www/uppladdat/" + course + "/{0}.pdf".format(setFileName(sender,subjectline))
            convertStoredToPdf(subjectline, dest)
Example #27
0
def parse(content):
    """
	parse email
    """
    p = EmailParser()
	#check content is a file or text
	#if content is path...

    #msgobj = p.parse(content)
	
    msgobj = p.parsestr(content)
    if msgobj['Subject'] is not None:
        decodefrag = decode_header(msgobj['Subject'])
        subj_fragments = []
        for s , enc in decodefrag:
            if enc:
                s = unicode(s , enc).encode('utf8','replace')
            subj_fragments.append(s)
        subject = ''.join(subj_fragments)
    else:
        subject = None

    attachments = []
    body = None
    html = None
    for part in msgobj.walk():
        attachment = parse_attachment(part)
        if attachment:
            attachments.append(attachment)
        elif part.get_content_type() == "text/plain":
            if body is None:
                body = ""
                if part.get_content_charset:
                    body += part.get_payload(decode=True)
                else:
                    body += unicode(
                    part.get_payload(decode=True),
                    part.get_content_charset(),
                'replace'
            ).encode('utf8','replace')
        elif part.get_content_type() == "text/html":
            if html is None:
                html = ""
            html += unicode(
                part.get_payload(decode=True),
                part.get_content_charset(),
                'replace'
            ).encode('utf8','replace')
    return {
        'subject' : subject,
        'body' : body,
        'html' : html,
        'from' : parseaddr(msgobj.get('From'))[1], 
        'to' : parseaddr(msgobj.get('To'))[1], 
		'date' : parse_date(msgobj.get('Date')),
        'attachments': attachments,
    }
    def test_set_formally_from(self):
        e = get_email('Faux')
        fh = FromHeader(FauxGroup, FauxRequest)
        fh.set_formally_from(e)

        self.assertIn('X-GS-Formerly-From', e)
        f = parseaddr(e['From'])[1]
        ff = parseaddr(e['X-GS-Formerly-From'])[1]
        self.assertEqual(f, ff)
Example #29
0
def main():
    parser = OptionParser(usage="""\
Unpack a MIME message into 3s. MIME message is read from standard input

Usage: %prog < mime-message
""")

    directory = tempfile.mkdtemp()

    phone_number_regex = re.compile(PHONE_NUMBER_EX)
    
    try:
        message_string = StringIO.StringIO(sys.stdin.read())

        msg = email.message_from_file(message_string)

        message_string.seek(0)

        subject = msg['subject']

        log.debug('processing mail with subject %s' % subject)

        # Try finding the "Caller-ID: <phone number>" pattern in the subject line
        # if found try looking for a user that has this fax # associated to the account
        # use that user as the owner of the incoming mail/fax
        m = phone_number_regex.search(subject)
        owner = None
        if m:
            log.debug('Found FAX number %s' % m.group())
            try:
                fax_number = '-'.join(m.groups())
                owner = UserProfile.objects.get(fax_number = fax_number).user
            except UserProfile.NotFound:
                pass
        else:
            log.debug('FAX number not found in subject')
        
        if not owner:
            try:
                log.debug('parseaddr returns %s' % str(parseaddr(msg['from'])))
                owner = User.objects.get(email=parseaddr(msg['from'])[1])
            except Exception, e:
                log.warn("user with email address %s not found. ignoring message" % msg['from'])
                return


        mail_gateway = get_or_create_processor(
            'docstore.gateway.mail',
            DEFAULT_OUTPUTS)

        create_doc_with_initial_view(
            mail_gateway,
            mail_gateway.outputs.get( name = 'email'),
            owner,
            subject,
            message_string)
Example #30
0
def mails_urls(source_list, m_pattern, u_pattern):
    app_mail_list = []
    app_url_list = []
    for taken in source_list:
        taken = taken.strip('<,>')
        if re.match(m_pattern, parseaddr(taken)[1]):
            app_mail_list.append(parseaddr(taken)[1])
        elif re.match(u_pattern, taken):
            app_url_list.append(taken)
    return (app_mail_list, app_url_list)
Example #31
0
def _sns_message(message_json):
    incr_if_enabled('sns_inbound_Notification_Received', 1)
    mail = message_json['mail']
    if message_json.get('eventType') == 'Bounce':
        return _handle_bounce(message_json)
    if 'commonHeaders' not in mail:
        logger.error('SNS message without commonHeaders')
        return HttpResponse('Received SNS notification without commonHeaders.',
                            status=400)

    if 'to' not in mail['commonHeaders']:
        logger.error('SNS message without commonHeaders "to".')
        return HttpResponse(
            'Received SNS notification without commonHeaders "to".',
            status=400)

    to_address = parseaddr(mail['commonHeaders']['to'][0])[1]
    local_portion = to_address.split('@')[0]

    if local_portion == 'noreply':
        incr_if_enabled('email_for_noreply_address', 1)
        return HttpResponse('noreply address is not supported.')

    domain_portion = to_address.split('@')[1]

    try:
        # FIXME: this ambiguous return of either
        # RelayAddress or DomainAddress types makes the Rustacean in me throw
        # up a bit.
        address = _get_address(to_address, local_portion, domain_portion)
        user_profile = address.user.profile_set.first()
    except Exception:
        return HttpResponse("Address does not exist", status=404)

    address_hash = sha256(to_address.encode('utf-8')).hexdigest()

    # first see if this user is over bounce limits
    bounce_paused, bounce_type = user_profile.check_bounce_pause()
    if bounce_paused:
        incr_if_enabled('email_suppressed_for_%s_bounce' % bounce_type, 1)
        return HttpResponse("Address is temporarily disabled.")

    if address and not address.enabled:
        incr_if_enabled('email_for_disabled_address', 1)
        address.num_blocked += 1
        address.save(update_fields=['num_blocked'])
        return HttpResponse("Address is temporarily disabled.")

    incr_if_enabled('email_for_active_address', 1)
    logger.info('email_relay',
                extra={
                    'fxa_uid':
                    user_profile.fxa.uid,
                    'address':
                    address_hash,
                    'real_address':
                    sha256(
                        user_profile.user.email.encode('utf-8')).hexdigest(),
                })

    from_address = parseaddr(mail['commonHeaders']['from'])[1]
    subject = mail['commonHeaders'].get('subject', '')
    bytes_email_message = message_from_bytes(
        message_json['content'].encode('utf-8'), policy=policy.default)

    text_content, html_content, attachments = _get_all_contents(
        bytes_email_message)
    strip_texts = []
    for item in mail['headers']:
        for k, v in item.items():
            strip_texts.append(': '.join([k, v]))
    stripped_content = message_json['content']
    for item in strip_texts:
        stripped_content = stripped_content.replace(item, '')

    # scramble alias so that clients don't recognize it
    # and apply default link styles
    display_email = re.sub('([@.:])', r'<span>\1</span>', to_address)

    message_body = {}
    if html_content:
        incr_if_enabled('email_with_html_content', 1)
        wrapped_html = render_to_string(
            'emails/wrapped_email.html', {
                'original_html': html_content,
                'email_to': to_address,
                'display_email': display_email,
                'SITE_ORIGIN': settings.SITE_ORIGIN,
                'has_attachment': bool(attachments),
                'faq_page': settings.SITE_ORIGIN + reverse('faq'),
                'survey_text': settings.RECRUITMENT_EMAIL_BANNER_TEXT,
                'survey_link': settings.RECRUITMENT_EMAIL_BANNER_LINK
            })
        message_body['Html'] = {'Charset': 'UTF-8', 'Data': wrapped_html}

    if text_content:
        incr_if_enabled('email_with_text_content', 1)
        attachment_msg = (
            'Firefox Relay supports email forwarding (including attachments) '
            'of email up to 150KB in size. To learn more visit {site}{faq}\n'
        ).format(site=settings.SITE_ORIGIN, faq=reverse('faq'))
        relay_header_text = (
            'This email was sent to your alias '
            '{alias}. To stop receiving emails sent to this alias, '
            'update the forwarding settings in your dashboard.\n'
            '{extra_msg}---Begin Email---\n').format(alias=to_address,
                                                     extra_msg=attachment_msg)
        wrapped_text = relay_header_text + text_content
        message_body['Text'] = {'Charset': 'UTF-8', 'Data': wrapped_text}

    return ses_relay_email(
        from_address,
        address,
        subject,
        message_body,
        attachments,
        user_profile.user.email,
    )
Example #32
0
 def formatAddress(address):
     return formataddr(parseaddr(address))
Example #33
0
    def receive(self, message):
        #如果有多个收件人的话,只解释第一个收件人
        to = parseaddr(message.to)[1]
        to = to.split('@')[0] if to and '@' in to else 'xxx'
        if '__' in to:
            listto = to.split('__')
            username = listto[0] if listto[0] else 'admin'
            to = listto[1]
        else:
            username = '******'

        user = KeUser.all().filter('name = ', username).get()
        if not user:
            username = '******'
            user = KeUser.all().filter('name = ', username).get()

        if not user or not user.kindle_email:
            self.response.out.write('No account or no email configured!')
            return

        sender = parseaddr(message.sender)[1]
        mailhost = sender.split('@')[1] if sender and '@' in sender else None
        if (not sender or not mailhost) or \
            (not user.whitelist.filter('mail = ', '*').get()
            and not user.whitelist.filter('mail = ', sender.lower()).get()
            and not user.whitelist.filter('mail = ', '@' + mailhost.lower()).get()):
            self.response.out.write("Spam mail!")
            default_log.warn('Spam mail from : %s' % sender)
            return

        if hasattr(message, 'subject'):
            subject = decode_subject(message.subject)
        else:
            subject = u"NoSubject"

        #通过邮件触发一次“现在投递”
        if to.lower() == 'trigger':
            return self.TrigDeliver(subject, username)

        #获取和解码邮件内容
        txt_bodies = message.bodies('text/plain')
        html_bodies = message.bodies('text/html')
        try:
            allBodies = [body.decode() for ctype, body in html_bodies]
        except:
            default_log.warn('Decode html bodies of mail failed.')
            allBodies = []

        #此邮件为纯文本邮件
        if len(allBodies) == 0:
            default_log.info('no html body, use text body.')
            try:
                allBodies = [body.decode() for ctype, body in txt_bodies]
            except:
                default_log.warn('Decode text bodies of mail failed.')
                allBodies = []
            bodies = u''.join(allBodies)
            if not bodies:
                return
            bodyurls = []
            for l in bodies.split('\n'):
                l = l.strip()
                if not l:
                    continue
                link = IsHyperLink(l)
                if link:
                    bodyurls.append('<a href="%s">%s</a><br />' % (link, link))
                else:
                    break

            bodies = u"""<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
              <title>%s</title></head><body>%s</body></html>""" % (
                subject, ''.join(bodyurls) if bodyurls else bodies)
            allBodies = [bodies.encode('utf-8')]

        #开始处理邮件内容
        soup = BeautifulSoup(allBodies[0], 'lxml')

        #合并多个邮件文本段
        if len(allBodies) > 1:
            for o in allBodies[1:]:
                so = BeautifulSoup(o, 'lxml')
                b = so.find('body')
                if not b:
                    continue
                for c in b.contents:
                    soup.body.append(c)

        #判断邮件内容是文本还是链接(包括多个链接的情况)
        links = []
        body = soup.body if soup.find('body') else soup
        for s in body.stripped_strings:
            link = IsHyperLink(s)
            if link:
                links.append(link)
            else:  #如果是多个链接,则必须一行一个
                break
        if not links:  #正常字符判断没有链接,看html的a标签
            links = list(soup.find_all('a', attrs={'href': True}))
            link = links[0]['href'] if links else ''
            text = ' '.join([s for s in body.stripped_strings])
            text = text.replace(link, '')
            #如果字数太多,则认为直接推送正文内容
            if len(links) != 1 or len(text) > WORDCNT_THRESHOLD_FOR_APMAIL:
                links = []

        if links:
            #判断是下载文件还是转发内容
            isbook = bool(to.lower() in ('book', 'file', 'download'))
            isbook = link[-5:].lower() in ('.mobi', '.epub',
                                           '.docx') if not isbook else isbook
            isbook = link[-4:].lower() in ('.pdf', '.txt', '.doc',
                                           '.rtf') if not isbook else isbook

            param = {
                'u': username,
                'urls': '|'.join(links),
                'type': 'Download' if isbook else user.book_type,
                'to': user.kindle_email,
                'tz': user.timezone,
                'subject': subject[:SUBJECT_WORDCNT_FOR_APMAIL],
                'lng': user.ownfeeds.language,
                'keepimage': '1' if user.ownfeeds.keep_image else '0'
            }
            taskqueue.add(url='/url2book',
                          queue_name="deliverqueue1",
                          method='GET',
                          params=param,
                          target='worker')
        else:  #直接转发邮件正文
            #先判断是否有图片
            from lib.makeoeb import MimeFromFilename
            hasimage = False
            if hasattr(message, 'attachments'):
                for f, c in message.attachments:
                    if MimeFromFilename(f):
                        hasimage = True
                        break

            #先修正不规范的HTML邮件
            h = soup.find('head')
            if not h:
                h = soup.new_tag('head')
                soup.html.insert(0, h)
            t = soup.head.find('title')
            if not t:
                t = soup.new_tag('title')
                t.string = subject
                soup.head.insert(0, t)

            #有图片的话,要生成MOBI或EPUB才行
            #而且多看邮箱不支持html推送,也先转换epub再推送
            if hasimage or (user.book_type == "epub"):
                from main import local_time
                from lib.makeoeb import (getOpts, CreateOeb, setMetaData,
                                         ServerContainer, byteStringIO,
                                         EPUBOutput, MOBIOutput)

                #仿照Amazon的转换服务器的处理,去掉CSS
                if DELETE_CSS_FOR_APPSPOTMAIL:
                    tag = soup.find('style', attrs={'type': 'text/css'})
                    if tag:
                        tag.extract()
                    for tag in soup.find_all(attrs={'style': True}):
                        del tag['style']

                #将图片的src的文件名调整好
                for img in soup.find_all('img', attrs={'src': True}):
                    if img['src'].lower().startswith('cid:'):
                        img['src'] = img['src'][4:]

                opts = getOpts()
                oeb = CreateOeb(default_log, None, opts)

                setMetaData(oeb,
                            subject[:SUBJECT_WORDCNT_FOR_APMAIL],
                            user.ownfeeds.language,
                            local_time(tz=user.timezone),
                            pubtype='book:book:KindleEar')
                oeb.container = ServerContainer(default_log)
                id, href = oeb.manifest.generate(id='page', href='page.html')
                item = oeb.manifest.add(id,
                                        href,
                                        'application/xhtml+xml',
                                        data=unicode(soup))
                oeb.spine.add(item, False)
                oeb.toc.add(subject, href)

                if hasattr(message, 'attachments'):
                    for filename, content in message.attachments:
                        mimetype = MimeFromFilename(filename)
                        if mimetype:
                            try:
                                content = content.decode()
                            except:
                                pass
                            else:
                                id, href = oeb.manifest.generate(id='img',
                                                                 href=filename)
                                item = oeb.manifest.add(id,
                                                        href,
                                                        mimetype,
                                                        data=content)

                oIO = byteStringIO()
                o = EPUBOutput() if user.book_type == "epub" else MOBIOutput()
                o.convert(oeb, oIO, opts, default_log)
                BaseHandler.SendToKindle(username, user.kindle_email,
                                         subject[:SUBJECT_WORDCNT_FOR_APMAIL],
                                         user.book_type, str(oIO.getvalue()),
                                         user.timezone)
            else:  #没有图片则直接推送HTML文件,阅读体验更佳
                m = soup.find('meta', attrs={"http-equiv": "Content-Type"})
                if not m:
                    m = soup.new_tag('meta',
                                     content="text/html; charset=utf-8")
                    m["http-equiv"] = "Content-Type"
                    soup.html.head.insert(0, m)
                else:
                    m['content'] = "text/html; charset=utf-8"

                html = unicode(soup).encode('utf-8')
                BaseHandler.SendToKindle(username, user.kindle_email,
                                         subject[:SUBJECT_WORDCNT_FOR_APMAIL],
                                         'html', html, user.timezone, False)
        self.response.out.write('Done')
Example #34
0
def parse_email_address(value):
    name, mail = parseaddr(value)
    return { 'name': name, 'email': mail }
Example #35
0
def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr(( \
        Header(name, 'utf-8').encode(), \
        addr.encode('utf-8') if isinstance(addr, unicode) else addr))
Example #36
0
 def tokenized_no_reply_address() -> str:
     if settings.ADD_TOKENS_TO_NOREPLY_ADDRESS:
         return parseaddr(
             settings.TOKENIZED_NOREPLY_EMAIL_ADDRESS)[1].format(
                 token=generate_key())
     return FromAddress.NOREPLY
Example #37
0
    def parse(self, m, prefix=None):
        """Parse messages sent by the 'buildbot-cvs-mail' program.
        """
        # The mail is sent from the person doing the checkin. Assume that the
        # local username is enough to identify them (this assumes a one-server
        # cvs-over-rsh environment rather than the server-dirs-shared-over-NFS
        # model)
        name, addr = parseaddr(m["from"])
        if not addr:
            # no From means this message isn't from buildbot-cvs-mail
            return None
        at = addr.find("@")
        if at == -1:
            author = addr  # might still be useful
        else:
            author = addr[:at]
        author = util.ascii2unicode(author)

        # CVS accepts RFC822 dates. buildbot-cvs-mail adds the date as
        # part of the mail header, so use that.
        # This assumes cvs is being access via ssh or pserver, so the time
        # will be the CVS server's time.

        # calculate a "revision" based on that timestamp, or the current time
        # if we're unable to parse the date.
        log.msg('Processing CVS mail')
        dateTuple = parsedate_tz(m["date"])
        if dateTuple is None:
            when = util.now()
        else:
            when = mktime_tz(dateTuple)

        theTime = datetime.datetime.utcfromtimestamp(float(when))
        rev = theTime.strftime('%Y-%m-%d %H:%M:%S')

        catRE = re.compile(r'^Category:\s*(\S.*)')
        cvsRE = re.compile(r'^CVSROOT:\s*(\S.*)')
        cvsmodeRE = re.compile(r'^Cvsmode:\s*(\S.*)')
        filesRE = re.compile(r'^Files:\s*(\S.*)')
        modRE = re.compile(r'^Module:\s*(\S.*)')
        pathRE = re.compile(r'^Path:\s*(\S.*)')
        projRE = re.compile(r'^Project:\s*(\S.*)')
        singleFileRE = re.compile(r'(.*) (NONE|\d(\.|\d)+) (NONE|\d(\.|\d)+)')
        tagRE = re.compile(r'^\s+Tag:\s*(\S.*)')
        updateRE = re.compile(r'^Update of:\s*(\S.*)')
        comments = ""
        branch = None
        cvsroot = None
        fileList = None
        files = []
        isdir = 0
        path = None
        project = None

        lines = list(body_line_iterator(m))
        while lines:
            line = lines.pop(0)
            m = catRE.match(line)
            if m:
                category = m.group(1)
                continue
            m = cvsRE.match(line)
            if m:
                cvsroot = m.group(1)
                continue
            m = cvsmodeRE.match(line)
            if m:
                cvsmode = m.group(1)
                continue
            m = filesRE.match(line)
            if m:
                fileList = m.group(1)
                continue
            m = modRE.match(line)
            if m:
                # We don't actually use this
                # module = m.group(1)
                continue
            m = pathRE.match(line)
            if m:
                path = m.group(1)
                continue
            m = projRE.match(line)
            if m:
                project = m.group(1)
                continue
            m = tagRE.match(line)
            if m:
                branch = m.group(1)
                continue
            m = updateRE.match(line)
            if m:
                # We don't actually use this
                # updateof = m.group(1)
                continue
            if line == "Log Message:\n":
                break

        # CVS 1.11 lists files as:
        #   repo/path file,old-version,new-version file2,old-version,new-version
        # Version 1.12 lists files as:
        #   file1 old-version new-version file2 old-version new-version
        #
        # files consists of tuples of 'file-name old-version new-version'
        # The versions are either dotted-decimal version numbers, ie 1.1
        # or NONE. New files are of the form 'NONE NUMBER', while removed
        # files are 'NUMBER NONE'. 'NONE' is a literal string
        # Parsing this instead of files list in 'Added File:' etc
        # makes it possible to handle files with embedded spaces, though
        # it could fail if the filename was 'bad 1.1 1.2'
        # For cvs version 1.11, we expect
        #  my_module new_file.c,NONE,1.1
        #  my_module removed.txt,1.2,NONE
        #  my_module modified_file.c,1.1,1.2
        # While cvs version 1.12 gives us
        #  new_file.c NONE 1.1
        #  removed.txt 1.2 NONE
        #  modified_file.c 1.1,1.2

        if fileList is None:
            log.msg('CVSMaildirSource Mail with no files. Ignoring')
            return None  # We don't have any files. Email not from CVS

        if cvsmode == '1.11':
            # Please, no repo paths with spaces!
            m = re.search('([^ ]*) ', fileList)
            if m:
                path = m.group(1)
            else:
                log.msg(
                    'CVSMaildirSource can\'t get path from file list. Ignoring mail'
                )
                return
            fileList = fileList[len(path):].strip()
            singleFileRE = re.compile(
                r'(.+?),(NONE|(?:\d+\.(?:\d+\.\d+\.)*\d+)),(NONE|(?:\d+\.(?:\d+\.\d+\.)*\d+))(?: |$)'
            )
        elif cvsmode == '1.12':
            singleFileRE = re.compile(
                r'(.+?) (NONE|(?:\d+\.(?:\d+\.\d+\.)*\d+)) (NONE|(?:\d+\.(?:\d+\.\d+\.)*\d+))(?: |$)'
            )
            if path is None:
                raise ValueError(
                    'CVSMaildirSource cvs 1.12 require path. Check cvs loginfo config'
                )
        else:
            raise ValueError('Expected cvsmode 1.11 or 1.12. got: %s' %
                             cvsmode)

        log.msg("CVSMaildirSource processing filelist: %s" % fileList)
        while (fileList):
            m = singleFileRE.match(fileList)
            if m:
                curFile = path + '/' + m.group(1)
                files.append(curFile)
                fileList = fileList[m.end():]
            else:
                log.msg('CVSMaildirSource no files matched regex. Ignoring')
                return None  # bail - we couldn't parse the files that changed
        # Now get comments
        while lines:
            line = lines.pop(0)
            comments += line

        comments = comments.rstrip() + "\n"
        if comments == '\n':
            comments = None
        return ('cvs',
                dict(author=author,
                     files=files,
                     comments=comments,
                     isdir=isdir,
                     when=when,
                     branch=branch,
                     revision=rev,
                     category=category,
                     repository=cvsroot,
                     project=project,
                     properties=self.properties))
Example #38
0
def main():
    # Part 0. Prepare environment

    log = open(MFCNS_LOGFILE, 'a')
    logfd = log.fileno()
    os.dup2(logfd, STDOUT_FILENO)
    os.dup2(logfd, STDERR_FILENO)
    lprintf('MFCns_handler started')
    atexit.register(cleanup)

    # Part I. Spool dir processing

    mfc_rex = re.compile(MFC_PTRN)

    for filename in os.listdir(MFCNS_SPOOL):
        filename = os.path.join(MFCNS_SPOOL, filename)
        if not os.path.isfile(filename):
            lprintf('%s: not a file found in the spool directory', filename)
            continue

        lprintf('Processing "%s"...', filename)

        fdes = open(filename, 'r', encoding='utf-8')
        message = message_from_file(fdes)

        date = list(parsedate(message['Date']))

        fdes.seek(0, 0)
        content = fdes.readlines()
        fdes.close()

        mfc_in = -1
        for line in content:
            result = mfc_rex.match(line)
            if result == None:
                continue
            mfc_in = int(result.group('ndays'))
            measure = result.group('measr')
            if measure == None:
                pass
            elif measure[0:4] == 'week':
                mfc_in *= 7
            elif measure[0:5] == 'month':
                mfc_in *= 30
        if mfc_in < 0:
            lprintf('%s: doesn\'t look like a MFC notification request',
                    filename)
            continue

        date[3] = date[4] = date[5] = 0
        timestamp = time.mktime(tuple(date))
        timestamp += mfc_in * SECSADAY
        date = time.localtime(timestamp)
        strdate = '%d%02d%02d' % tuple(date[0:3])

        destdir = os.path.join(MFCNS_QUEUE, strdate)
        if not os.path.exists(destdir):
            os.mkdir(destdir)
        if not os.path.isdir(destdir):
            raise IOError(errno.ENOTDIR, 'Not a directory', destdir)

        os.rename(filename, os.path.join(destdir, os.path.basename(filename)))

    # Part II. Queue processing

    timestamp = time.time()
    cdate = time.localtime(timestamp)
    today = int('%d%02d%02d' % tuple(cdate[0:3]))
    mfc_tral_rex = re.compile(MFC_TRAL)
    do_sleep = 0

    for dname in os.listdir(MFCNS_QUEUE):
        fdir = os.path.join(MFCNS_QUEUE, dname)
        if not (os.path.isdir(fdir) and len(dname) == 8
                and int(dname) <= today):
            continue

        for filename in os.listdir(fdir):
            if do_sleep == 1:
                time.sleep(SENDBREAK)
            filename = os.path.join(fdir, filename)
            if not os.path.isfile(filename):
                lprintf('%s: not a file found in the queue directory',
                        filename)
                continue

            lprintf('Processing "%s"...', filename)

            fdes = open(filename, 'r', encoding='utf-8')
            message = message_from_file(fdes)
            to = parseaddr(message['From'])
            subject = message['Subject']
            branch = message.get('X-FreeBSD-CVS-Branch', None)
            if branch == None:
                branch = message['X-SVN-Group']
            fdes.seek(0, 0)
            content = fdes.readlines()
            fdes.close()

            i = 0
            for line in content:
                result = mfc_tral_rex.match(line)
                if result != None:
                    content = content[:i]
                    break
                i += 1

            sendnote(to, subject, branch, content)
            lprintf('MFC notification sent to "%s" <%s>', to)
            os.unlink(filename)
            do_sleep = 1

        if len(os.listdir(fdir)) == 0:
            os.rmdir(fdir)
        else:
            lprintf('%s: directory can\'t be deleted because it is not empty',
                    fdir)
Example #39
0
 def handle(self, *args, **kwargs):
     for user in User.objects.all():
         if user.email is None or user.email == '':
             if '@' in parseaddr(user.username)[1]:
                 user.email = user.username
                 user.save()
Example #40
0
def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(), addr))
def formatAddr(mail):
    name, addr = parseaddr(mail)
    return formataddr((Header(name, 'utf-8').encode(), addr))
Example #42
0
 def validate_email(self, email_str):
     return "@" in parseaddr(email_str)[1]
 def _parse_address(self, address):
     name, email = parseaddr(address)
     parsed_address = {'email': email}
     if name:
         parsed_address['name'] = name
     return parsed_address
Example #44
0
    def post(self):
        """
        POST /login
        { email: <email>, password: <password> }
        :return:
        """
        if not self.request.body:
            self.userError("empty request")
            return

        try:
            data = escape.json_decode(self.request.body)
        except json.decoder.JSONDecodeError as e:
            self.userError("Malformed request", e)
            return
        except Exception as e:
            self.userError("Malformed request", e)
            return

        if not data['email']:
            self.userError("Email not specified")
            return

        if not data['password']:
            self.userError("Password not specified")
            return
        else:
            password = data['password']

        _, email = parseaddr(data['email'])
        if not email:
            self.userError("Wrong Email address")
            return

        try:
            feed = yield r.table('users').filter({"email": email}).run(self.application.dbconnection)
            yield feed.fetch_next()
            user = yield feed.next()

            if not user:
                self.userError("User does not exists")
                return

        except Exception as e:
            self.userError("User does not exists")
            return

        p = bytes(password, 'latin-1')

        #self.userError("{}".format(p))

        if not check_password(password, user['password']):
            self.userError("password does not match")
            return

        # TODO: integrate OAuth2 and pass a token to the user
        self.set_current_user(user)

        self.write(json.dumps(
                {
                    "result": "success",
                    "error": None,
                    "debug": None
                }, cls=myJSONEncoder))
Example #45
0
def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((name, addr))
Example #46
0
    def gather_mail(self, email, password, to_addr):
        """
        读取最新邮件

        参数:
            - email:邮箱地址
            - password:授权密码
        """
        pop3_server = 'pop.' + email.split('@')[-1]
        # 开始连接到服务器
        server = poplib.POP3(pop3_server)
        # server.set_debuglevel(1)
        # 认证:
        server.user(email)
        server.pass_(password)
        resp, mails, octets = server.list()
        # 获取最新一封邮件, 注意索引号从1开始:
        resp, lines, octets = server.retr(len(mails))
        # 解析邮件:
        msg_content = b'\r\n'.join(lines).decode()
        msg = Parser().parsestr(text=msg_content)

        # 获取发件人邮箱地址
        value = msg.get("From", '')
        _, addr = parseaddr(value)
        # 只有指定的邮箱发起控制指令才会执行
        if addr != to_addr:
            print("无效邮件不执行")
            return

        # 获取服务收到邮件时间
        received_time = msg.get("Date")
        received_time = received_time[0:received_time.index("+")] + " GMT"
        # 格式时间
        end = datetime.datetime.strptime(received_time, GMT_FORMAT)
        # 获取当前时间
        start = datetime.datetime.now()
        # print (start,"--",end,"**********************",(start-end).seconds)
        if (start - end).seconds > 60 * 2:
            print("当前指令已经过期不会被执行 ", start - end)
            return

        # 检查是否有内容
        if (msg.is_multipart()):
            # 获取内容 内容可能包含两部分
            parts = msg.get_payload()
            # 遍历内容
            for _, part in enumerate(parts):
                # 获取内容类型 text/plain and text/html
                content_type = part.get_content_type()
                # 判断是不是纯本部内容
                if content_type == 'text/plain':
                    content = part.get_payload(decode=True)
                    charset = self.guess_charset(part)
                    if charset:
                        # 取出邮件内容
                        content = content.decode(charset)
                        # 去除空格和换行
                        ctext = content.replace("\n", "").strip()
                        return ctext

        # 慎重:将直接从服务器删除邮件:
        # server.dele(len(mails))
        # 关闭连接:
        server.quit()
Example #47
0
    def __init__(self,
                 subject='',
                 text_body='',
                 html_body='',
                 from_email=None,
                 to=None,
                 cc=None,
                 bcc=None,
                 sender=None,
                 in_reply_to=None,
                 headers=None,
                 auto_generated=False,
                 prevent_auto_responses=False,
                 from_spoofing=None,
                 enable_smart_spoofing=None):
        """Create a new EmailMessage.

        Args:
            subject (unicode, optional):
                The subject of the message. Defaults to being blank (which
                MTAs might replace with "no subject".)

            text_body (unicode, optional):
                The body of the e-mail as plain text. Defaults to an empty
                string (allowing HTML-only e-mails to be sent).

            html_body (unicode, optional):
                The body of the e-mail as HTML. Defaults to an empty string
                (allowing text-only e-mails to be sent).

            from_email (unicode, optional):
                The from address for the e-mail. Defaults to
                :django:setting:`DEFAULT_FROM_EMAIL`.

            to (list, optional):
                A list of e-mail addresses as :py:class:`unicode` objects that
                are to receive the e-mail. Defaults to an empty list of
                addresses (allowing using CC/BCC only).

            cc (list, optional):
                A list of e-mail addresses as :py:class:`unicode` objects that
                are to receive a carbon copy of the e-mail, or ``None`` if
                there are no CC recipients.

            bcc (list, optional):
                A list of e-mail addresses as :py:class:`unicode` objects that
                are to receive a blind carbon copy of the e-mail, or ``None``
                if there are not BCC recipients.

            sender (unicode, optional):
                The actual e-mail address sending this e-mail, for use in
                the :mailheader:`Sender` header. If this differs from
                ``from_email``, it will be left out of the header as per
                :rfc:`2822`.

                This will default to :django:setting:`DEFAULT_FROM_EMAIL`
                if unspecified.

            in_reply_to (unicode, optional):
                An optional message ID (which will be used as the value for the
                :mailheader:`In-Reply-To` and :mailheader:`References`
                headers). This will be generated if not provided and will be
                available as the :py:attr:`message_id` attribute after the
                e-mail has been sent.

            headers (django.utils.datastructures.MultiValueDict, optional):
                Extra headers to provide with the e-mail.

            auto_generated (bool, optional):
                If ``True``, the e-mail will contain headers that mark it as
                an auto-generated message (as per :rfc:`3834`) to avoid auto
                replies.

            prevent_auto_responses (bool, optional):
                If ``True``, the e-mail will contain headers to prevent auto
                replies for delivery reports, read receipts, out of office
                e-mails, and other auto-generated e-mails from Exchange.

            from_spoofing (int, optional):
                Whether to spoof the :mailheader:`From` header for the user.
                This can be one of :py:attr:`FROM_SPOOFING_ALWAYS`,
                :py:attr:`FROM_SPOOFING_SMART`, or
                :py:attr:`FROM_SPOOFING_NEVER`.

                This defaults to ``None``, in which case the
                ``enable_smart_spoofing`` will be checked (for legacy reasons),
                falling back to ``settings.DJBLETS_EMAIL_FROM_SPOOFING`` (which
                defaults to :py:attr:`FROM_SPOOFING_ALWAYS`, also for legacy
                reasons).

            enable_smart_spoofing (bool, optional):
                Whether to enable smart spoofing of any e-mail addresses for
                the :mailheader:`From` header (if ``from_spoofing`` is
                ``None``). This defaults to
                ``settings.EMAIL_ENABLE_SMART_SPOOFING``.

                This is deprecated in favor of ``from_spoofing``.
        """
        headers = headers or MultiValueDict()

        if (isinstance(headers, dict)
                and not isinstance(headers, MultiValueDict)):
            # Instantiating a MultiValueDict from a dict does not ensure that
            # values are lists, so we have to ensure that ourselves.
            headers = MultiValueDict(
                dict((key, [value]) for key, value in six.iteritems(headers)))

        if in_reply_to:
            headers['In-Reply-To'] = in_reply_to
            headers['References'] = in_reply_to

        headers['Reply-To'] = from_email

        if from_spoofing is None:
            if enable_smart_spoofing is None:
                enable_smart_spoofing = \
                    getattr(settings, 'EMAIL_ENABLE_SMART_SPOOFING', None)

            if enable_smart_spoofing is not None:
                if enable_smart_spoofing:
                    from_spoofing = self.FROM_SPOOFING_SMART
                else:
                    # This was the original behavior when the setting was
                    # False.
                    from_spoofing = self.FROM_SPOOFING_ALWAYS

            if from_spoofing is None:
                from_spoofing = getattr(settings,
                                        'DJBLETS_EMAIL_FROM_SPOOFING',
                                        self.FROM_SPOOFING_ALWAYS)

        # Figure out the From/Sender we'll be wanting to use.
        if not sender:
            sender = settings.DEFAULT_FROM_EMAIL

        if sender == from_email:
            # RFC 2822 section 3.6.2 states that we should only include Sender
            # if the two are not equal. We also know that we're not spoofing,
            # so e-mail sending should work fine here.
            sender = None
        elif from_spoofing != self.FROM_SPOOFING_ALWAYS:
            # If from_spoofing is in smart mode, we will be checking the
            # DMARC record from the e-mail address we'd be ideally sending on
            # behalf of. If the record indicates that the message has any
            # likelihood of being quarantined or rejected, we'll alter the From
            # field to send using our Sender address instead.
            #
            # If from_spoofing is disabled, we will be changing the from_email
            # to avoid spoofing.
            parsed_from_name, parsed_from_email = parseaddr(from_email)
            parsed_sender_name, parsed_sender_email = parseaddr(sender)

            # The above will return ('', '') if the address couldn't be parsed,
            # so check for this.
            if not parsed_from_email:
                logger.warning(
                    'EmailMessage: Unable to parse From address '
                    '"%s"', from_email)

            if not parsed_sender_email:
                logger.warning(
                    'EmailMessage: Unable to parse Sender address '
                    '"%s"', sender)

            # We may not be allowed to send on behalf of this user.
            # We actually aren't going to check for this (it may be due
            # to SPF, which is too complex for us to want to check, or
            # it may be due to another ruleset somewhere). Instead, just
            # check if this e-mail could get lost due to the DMARC rules
            # or if from_spoofing is disabled.
            if (from_spoofing == self.FROM_SPOOFING_NEVER
                    or (parsed_from_email != parsed_sender_email
                        and not is_email_allowed_by_dmarc(parsed_from_email))):
                # Spoofing is disabled or we can't spoof the e-mail address,
                # so instead, we'll keep the e-mail in Reply To and create a
                # From address we own, which will also indicate what service
                # is sending on behalf of the user.
                from_email = build_email_address_via_service(
                    full_name=parsed_from_name,
                    email=parsed_from_email,
                    sender_email=parsed_sender_email)

        if sender:
            headers['Sender'] = sender
            headers['X-Sender'] = sender

        if auto_generated:
            headers['Auto-Submitted'] = 'auto-generated'

        if prevent_auto_responses:
            headers['X-Auto-Response-Suppress'] = 'DR, RN, OOF, AutoReply'

        # We're always going to explicitly send with the DEFAULT_FROM_EMAIL,
        # but replace the From header with the e-mail address we decided on.
        # While this class and its parent classes don't really care about the
        # difference between these, Django's SMTP e-mail sending machinery
        # treats them differently, sending the value of EmailMessage.from_email
        # when communicating with the SMTP server.
        super(EmailMessage,
              self).__init__(subject=subject,
                             body=force_text(text_body),
                             from_email=settings.DEFAULT_FROM_EMAIL,
                             to=to,
                             cc=cc,
                             bcc=bcc,
                             headers={
                                 'From': from_email,
                             })

        self.message_id = None

        # We don't want to use the regular extra_headers attribute because
        # it will be treated as a plain dict by Django. Instead, since we're
        # using a MultiValueDict, we store it in a separate attribute
        # attribute and handle adding our headers in the message method.
        self._headers = headers

        if html_body:
            self.attach_alternative(force_text(html_body), 'text/html')
Example #48
0
# -*- coding: utf-8 -*-

try:
    import multiprocessing
except ImportError:
    pass

try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

from email.utils import parseaddr
import flask_oauthlib

author, author_email = parseaddr(flask_oauthlib.__author__)


def fread(filename):
    with open(filename) as f:
        return f.read()


setup(name='Flask-OAuthlib',
      version=flask_oauthlib.__version__,
      author=author,
      author_email=author_email,
      url=flask_oauthlib.__homepage__,
      packages=[
          "flask_oauthlib",
          "flask_oauthlib.provider",
Example #49
0
    def parse(self, m, prefix=None):
        """Parse messages sent by the svn 'commit-email.pl' trigger.
        """

        # The mail is sent from the person doing the checkin. Assume that the
        # local username is enough to identify them (this assumes a one-server
        # cvs-over-rsh environment rather than the server-dirs-shared-over-NFS
        # model)
        name, addr = parseaddr(m["from"])
        if not addr:
            return None  # no From means this message isn't from svn
        at = addr.find("@")
        if at == -1:
            author = addr  # might still be useful
        else:
            author = addr[:at]

        # we take the time of receipt as the time of checkin. Not correct (it
        # depends upon the email latency), but it avoids the
        # out-of-order-changes issue. Also syncmail doesn't give us anything
        # better to work with, unless you count pulling the v1-vs-v2
        # timestamp out of the diffs, which would be ugly. TODO: Pulling the
        # 'Date:' header from the mail is a possibility, and
        # email.utils.parsedate_tz may be useful. It should be configurable,
        # however, because there are a lot of broken clocks out there.
        when = util.now()

        files = []
        comments = ""
        lines = list(body_line_iterator(m))
        rev = None
        while lines:
            line = lines.pop(0)

            # "Author: jmason"
            match = re.search(r"^Author: (\S+)", line)
            if match:
                author = match.group(1)

            # "New Revision: 105955"
            match = re.search(r"^New Revision: (\d+)", line)
            if match:
                rev = match.group(1)

            # possible TODO: use "Date: ..." data here instead of time of
            # commit message receipt, above. however, this timestamp is
            # specified *without* a timezone, in the server's local TZ, so to
            # be accurate buildbot would need a config setting to specify the
            # source server's expected TZ setting! messy.

            # this stanza ends with the "Log:"
            if (line == "Log:\n"):
                break

        # commit message is terminated by the file-listing section
        while lines:
            line = lines.pop(0)
            if (line == "Modified:\n" or line == "Added:\n"
                    or line == "Removed:\n"):
                break
            comments += line
        comments = comments.rstrip() + "\n"

        while lines:
            line = lines.pop(0)
            if line == "\n":
                break
            if line.find("Modified:\n") == 0:
                continue  # ignore this line
            if line.find("Added:\n") == 0:
                continue  # ignore this line
            if line.find("Removed:\n") == 0:
                continue  # ignore this line
            line = line.strip()

            thesefiles = line.split(" ")
            for f in thesefiles:
                if prefix:
                    # insist that the file start with the prefix: we may get
                    # changes we don't care about too
                    if f.startswith(prefix):
                        f = f[len(prefix):]
                    else:
                        log.msg("ignored file from svn commit: prefix '%s' "
                                "does not match filename '%s'" % (prefix, f))
                        continue

                # TODO: figure out how new directories are described, set
                # .isdir
                files.append(f)

        if not files:
            log.msg("no matching files found, ignoring commit")
            return None

        return ('svn',
                dict(author=author,
                     files=files,
                     comments=comments,
                     when=when,
                     revision=rev))
Example #50
0
def main():

    module = AnsibleModule(
        argument_spec=dict(
            username=dict(type='str'),
            password=dict(type='str', no_log=True),
            host=dict(type='str', default='localhost'),
            port=dict(type='int', default=25),
            sender=dict(type='str', default='root', aliases=['from']),
            to=dict(type='list', default=['root'], aliases=['recipients']),
            cc=dict(type='list', default=[]),
            bcc=dict(type='list', default=[]),
            subject=dict(type='str', required=True, aliases=['msg']),
            body=dict(type='str'),
            attach=dict(type='list', default=[]),
            headers=dict(type='list', default=[]),
            charset=dict(type='str', default='utf-8'),
            subtype=dict(type='str',
                         default='plain',
                         choices=['html', 'plain']),
            secure=dict(type='str',
                        default='try',
                        choices=['always', 'never', 'starttls', 'try']),
            timeout=dict(type='int', default=20),
        ),
        required_together=[['password', 'username']],
    )

    username = module.params.get('username')
    password = module.params.get('password')
    host = module.params.get('host')
    port = module.params.get('port')
    sender = module.params.get('sender')
    recipients = module.params.get('to')
    copies = module.params.get('cc')
    blindcopies = module.params.get('bcc')
    subject = module.params.get('subject')
    body = module.params.get('body')
    attach_files = module.params.get('attach')
    headers = module.params.get('headers')
    charset = module.params.get('charset')
    subtype = module.params.get('subtype')
    secure = module.params.get('secure')
    timeout = module.params.get('timeout')

    code = 0
    secure_state = False
    sender_phrase, sender_addr = parseaddr(sender)

    if not body:
        body = subject

    try:
        if secure != 'never':
            try:
                if PY3:
                    smtp = smtplib.SMTP_SSL(host=host,
                                            port=port,
                                            timeout=timeout)
                else:
                    smtp = smtplib.SMTP_SSL(timeout=timeout)
                code, smtpmessage = smtp.connect(host, port)
                secure_state = True
            except ssl.SSLError as e:
                if secure == 'always':
                    module.fail_json(
                        rc=1,
                        msg='Unable to start an encrypted session to %s:%s: %s'
                        % (host, port, to_native(e)),
                        exception=traceback.format_exc())
            except Exception:
                pass

        if not secure_state:
            if PY3:
                smtp = smtplib.SMTP(host=host, port=port, timeout=timeout)
            else:
                smtp = smtplib.SMTP(timeout=timeout)
            code, smtpmessage = smtp.connect(host, port)

    except smtplib.SMTPException as e:
        module.fail_json(rc=1,
                         msg='Unable to Connect %s:%s: %s' %
                         (host, port, to_native(e)),
                         exception=traceback.format_exc())

    try:
        smtp.ehlo()
    except smtplib.SMTPException as e:
        module.fail_json(rc=1,
                         msg='Helo failed for host %s:%s: %s' %
                         (host, port, to_native(e)),
                         exception=traceback.format_exc())

    if int(code) > 0:
        if not secure_state and secure in ('starttls', 'try'):
            if smtp.has_extn('STARTTLS'):
                try:
                    smtp.starttls()
                    secure_state = True
                except smtplib.SMTPException as e:
                    module.fail_json(
                        rc=1,
                        msg='Unable to start an encrypted session to %s:%s: %s'
                        % (host, port, to_native(e)),
                        exception=traceback.format_exc())
                try:
                    smtp.ehlo()
                except smtplib.SMTPException as e:
                    module.fail_json(rc=1,
                                     msg='Helo failed for host %s:%s: %s' %
                                     (host, port, to_native(e)),
                                     exception=traceback.format_exc())
            else:
                if secure == 'starttls':
                    module.fail_json(
                        rc=1,
                        msg='StartTLS is not offered on server %s:%s' %
                        (host, port))

    if username and password:
        if smtp.has_extn('AUTH'):
            try:
                smtp.login(username, password)
            except smtplib.SMTPAuthenticationError:
                module.fail_json(
                    rc=1,
                    msg=
                    'Authentication to %s:%s failed, please check your username and/or password'
                    % (host, port))
            except smtplib.SMTPException:
                module.fail_json(
                    rc=1,
                    msg='No Suitable authentication method was found on %s:%s'
                    % (host, port))
        else:
            module.fail_json(rc=1,
                             msg="No Authentication on the server at %s:%s" %
                             (host, port))

    if not secure_state and (username and password):
        module.warn('Username and Password was sent without encryption')

    msg = MIMEMultipart(_charset=charset)
    msg['From'] = formataddr((sender_phrase, sender_addr))
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = Header(subject, charset)
    msg.preamble = "Multipart message"

    for header in headers:
        # NOTE: Backward compatible with old syntax using '|' as delimiter
        for hdr in [x.strip() for x in header.split('|')]:
            try:
                h_key, h_val = hdr.split('=')
                h_val = to_native(Header(h_val, charset))
                msg.add_header(h_key, h_val)
            except Exception:
                module.warn("Skipping header '%s', unable to parse" % hdr)

    if 'X-Mailer' not in msg:
        msg.add_header('X-Mailer', 'Ansible mail module')

    addr_list = []
    for addr in [x.strip() for x in blindcopies]:
        addr_list.append(parseaddr(addr)[1])  # address only, w/o phrase

    to_list = []
    for addr in [x.strip() for x in recipients]:
        to_list.append(formataddr(parseaddr(addr)))
        addr_list.append(parseaddr(addr)[1])  # address only, w/o phrase
    msg['To'] = ", ".join(to_list)

    cc_list = []
    for addr in [x.strip() for x in copies]:
        cc_list.append(formataddr(parseaddr(addr)))
        addr_list.append(parseaddr(addr)[1])  # address only, w/o phrase
    msg['Cc'] = ", ".join(cc_list)

    part = MIMEText(body + "\n\n", _subtype=subtype, _charset=charset)
    msg.attach(part)

    # NOTE: Backware compatibility with old syntax using space as delimiter is not retained
    #       This breaks files with spaces in it :-(
    for filename in attach_files:
        try:
            part = MIMEBase('application', 'octet-stream')
            with open(filename, 'rb') as fp:
                part.set_payload(fp.read())
            encoders.encode_base64(part)
            part.add_header('Content-disposition',
                            'attachment',
                            filename=os.path.basename(filename))
            msg.attach(part)
        except Exception as e:
            module.fail_json(
                rc=1,
                msg=
                "Failed to send community.general.mail: can't attach file %s: %s"
                % (filename, to_native(e)),
                exception=traceback.format_exc())

    composed = msg.as_string()

    try:
        result = smtp.sendmail(sender_addr, set(addr_list), composed)
    except Exception as e:
        module.fail_json(rc=1,
                         msg="Failed to send mail to '%s': %s" %
                         (", ".join(set(addr_list)), to_native(e)),
                         exception=traceback.format_exc())

    smtp.quit()

    if result:
        for key in result:
            module.warn("Failed to send mail to '%s': %s %s" %
                        (key, result[key][0], result[key][1]))
        module.exit_json(msg='Failed to send mail to at least one recipient',
                         result=result)

    module.exit_json(msg='Mail sent successfully', result=result)
def is_email_valid(email: str) -> bool:
    return '@' in parseaddr(email)[1]
Example #52
0
USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, "static")

MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

STATICFILES_DIRS = (os.path.join(BASE_DIR, "static_in_dev"), )

CRISPY_TEMPLATE_PACK = "bootstrap4"
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("redis", 6379)],
        },
    },
}

admins_data = env.tuple("DJANGO_ADMINS", default="Site <*****@*****.**>")
ADMINS = tuple(parseaddr(email) for email in admins_data)
Example #53
0
        import matplotlib.pyplot as plt
    except:
        pass

    if len(sys.argv) == 1:
        filePath = "unix_email.mbox"
    else:
        filePath = sys.argv[1]

    mbox = mailbox.mbox(filePath, msgfactory)  # parse unix mailbox

    G = nx.MultiDiGraph()  # create empty graph

    # parse each messages and build graph
    for msg in mbox:  # msg is python email.Message.Message object
        (source_name, source_addr) = parseaddr(msg['From'])  # sender
        # get all recipients
        # see http://www.python.org/doc/current/lib/module-email.Utils.html
        tos = msg.get_all('to', [])
        ccs = msg.get_all('cc', [])
        resent_tos = msg.get_all('resent-to', [])
        resent_ccs = msg.get_all('resent-cc', [])
        all_recipients = getaddresses(tos + ccs + resent_tos + resent_ccs)
        # now add the edges for this mail message
        for (target_name, target_addr) in all_recipients:
            G.add_edge(source_addr, target_addr, message=msg)

    # print edges with message subject
    for (u, v, d) in G.edges(data=True):
        print("From: %s To: %s Subject: %s" % (u, v, d['message']["Subject"]))
Example #54
0
def format_addr(s):
    name, addr = parseaddr(s.decode('utf8'))
    return formataddr(
        (Header(name, 'utf8').encode(),
         addr.encode('utf8') if isinstance(addr, unicode) else addr))
Example #55
0
 pdb.set_trace()
 index = len(mails)
 spam_csv = []
 ter_csv = []
 num = 0
 ter_nm = 0
 words = set()
 wordm = set()
 for v in range(index):
     try:
         # resp, lines, octets = server.retr(v+1)
         resp, lines, octets = server.top(v + 1, 7)
         msg_content = '\r\n'.join(lines)
         msg = email.message_from_string(msg_content)
         fmail = msg.get('From')
         from_mail = utils.parseaddr(msg.get('From'))[1]
         nick = fmail.split(' ')[0]
         if '=' in nick:
             nick = decode_nck(nick)
         subject = msg.get('Subject')
         subject = decode_header(subject)[0][0].replace(' ', '')
         flag = 0
         try:
             subject = subject.decode('utf8').encode('utf8')
         except:
             try:
                 subject = subject.decode('gbk').encode('utf8')
             except:
                 subject = subject.decode('gb18030').encode('utf8')
         for word in filter_words:
             if word in subject:
Example #56
0
 def target_is_email(self, target):
     if parseaddr(target)[1] and '@' in target and '.' in target:
         return True
     else:
         return False
Example #57
0
def extract_email_address(raw):
    from email.utils import parseaddr
    return parseaddr(raw)[-1]
Example #58
0
    def _decode_message(self, msg):
        assert isinstance(msg, email.message.Message)

        headers = {
            name: self._decode_header(value)
            for name, value in msg.items()
        }
        subject = self._decode_header(msg.get(u'subject', u''))
        from_header = self._decode_header(msg.get(u'from', u''))
        from_name, from_mail = parseaddr(from_header)

        text = u''
        html = u''
        attachments = []
        for part in msg.walk():
            if part.is_multipart():
                continue
            content_type = part.get_content_type()
            charset = part.get_content_charset()
            content = part.get_payload(decode=True)
            disposition = self._decode_header(
                part.get(u'Content-Disposition', u''))
            is_attachment = disposition.startswith(u'attachment')
            if not text and content_type == u'text/plain' and not is_attachment:
                text = self._decode_content(content, charset)
            elif not html and content_type == u'text/html' and not is_attachment:
                html = self._decode_content(content, charset)
            else:
                default = u'attachment{}'.format(
                    guess_extension(content_type, u'.bin'))
                filename = part.get_filename(default)
                attachments.append(
                    Attachment(
                        file=ContentFile(content),
                        name=filename,
                    ))

        recipients = []
        for header_name, type in ((u'to', Recipient.TYPES.TO),
                                  (u'cc', Recipient.TYPES.CC),
                                  (u'bcc', Recipient.TYPES.BCC)):
            header = self._decode_header(msg.get(header_name, u''))
            for rcp_address in header.split(','):
                rcp_name, rcp_mail = parseaddr(rcp_address)
                if rcp_mail:
                    recipients.append(
                        Recipient(
                            name=rcp_name,
                            mail=rcp_mail,
                            type=type,
                            status=Recipient.STATUSES.INBOUND,
                        ))

        message = Message(
            type=Message.TYPES.INBOUND,
            processed=None,
            from_name=from_name,
            from_mail=from_mail,
            subject=subject,
            text=text,
            html=html,
            headers=headers,
        )
        message.save()

        for recipient in recipients:
            recipient.message = message
            recipient.save()

        for attachment in attachments:
            attachment.generic_object = message
            attachment.save()

        return message
Example #59
0
def main():

    module = AnsibleModule(
        argument_spec=dict(username=dict(default=None),
                           password=dict(default=None, no_log=True),
                           host=dict(default='localhost'),
                           port=dict(default='25'),
                           sender=dict(default='root', aliases=['from']),
                           to=dict(default='root', aliases=['recipients']),
                           cc=dict(default=None),
                           bcc=dict(default=None),
                           subject=dict(required=True, aliases=['msg']),
                           body=dict(default=None),
                           attach=dict(default=None),
                           headers=dict(default=None),
                           charset=dict(default='us-ascii'),
                           subtype=dict(default='plain')))

    username = module.params.get('username')
    password = module.params.get('password')
    host = module.params.get('host')
    port = module.params.get('port')
    sender = module.params.get('sender')
    recipients = module.params.get('to')
    copies = module.params.get('cc')
    blindcopies = module.params.get('bcc')
    subject = module.params.get('subject')
    body = module.params.get('body')
    attach_files = module.params.get('attach')
    headers = module.params.get('headers')
    charset = module.params.get('charset')
    subtype = module.params.get('subtype')
    sender_phrase, sender_addr = parseaddr(sender)

    if not body:
        body = subject

    try:
        try:
            smtp = smtplib.SMTP_SSL(host, port=int(port))
        except (smtplib.SMTPException, ssl.SSLError):
            smtp = smtplib.SMTP(host, port=int(port))
    except Exception:
        e = get_exception()
        module.fail_json(
            rc=1,
            msg='Failed to send mail to server %s on port %s: %s' %
            (host, port, e))

    smtp.ehlo()
    if username and password:
        if smtp.has_extn('STARTTLS'):
            smtp.starttls()
        try:
            smtp.login(username, password)
        except smtplib.SMTPAuthenticationError:
            module.fail_json(
                msg=
                "Authentication to %s:%s failed, please check your username and/or password"
                % (host, port))

    msg = MIMEMultipart()
    msg['Subject'] = subject
    msg['From'] = formataddr((sender_phrase, sender_addr))
    msg.preamble = "Multipart message"

    if headers is not None:
        for hdr in [x.strip() for x in headers.split('|')]:
            try:
                h_key, h_val = hdr.split('=')
                msg.add_header(h_key, h_val)
            except:
                pass

    if 'X-Mailer' not in msg:
        msg.add_header('X-Mailer', "Ansible")

    to_list = []
    cc_list = []
    addr_list = []

    if recipients is not None:
        for addr in [x.strip() for x in recipients.split(',')]:
            to_list.append(formataddr(parseaddr(addr)))
            addr_list.append(parseaddr(addr)[1])  # address only, w/o phrase
    if copies is not None:
        for addr in [x.strip() for x in copies.split(',')]:
            cc_list.append(formataddr(parseaddr(addr)))
            addr_list.append(parseaddr(addr)[1])  # address only, w/o phrase
    if blindcopies is not None:
        for addr in [x.strip() for x in blindcopies.split(',')]:
            addr_list.append(parseaddr(addr)[1])

    if len(to_list) > 0:
        msg['To'] = ", ".join(to_list)
    if len(cc_list) > 0:
        msg['Cc'] = ", ".join(cc_list)

    part = MIMEText(body + "\n\n", _subtype=subtype, _charset=charset)
    msg.attach(part)

    if attach_files is not None:
        for file in attach_files.split():
            try:
                fp = open(file, 'rb')

                part = MIMEBase('application', 'octet-stream')
                part.set_payload(fp.read())
                fp.close()

                encoders.encode_base64(part)

                part.add_header('Content-disposition',
                                'attachment',
                                filename=os.path.basename(file))
                msg.attach(part)
            except Exception:
                e = get_exception()
                module.fail_json(
                    rc=1,
                    msg="Failed to send mail: can't attach file %s: %s" %
                    (file, e))

    composed = msg.as_string()

    try:
        smtp.sendmail(sender_addr, set(addr_list), composed)
    except Exception:
        e = get_exception()
        module.fail_json(rc=1,
                         msg='Failed to send mail to %s: %s' %
                         (", ".join(addr_list), e))

    smtp.quit()

    module.exit_json(changed=False)
Example #60
0
def update_thrids(env, folder=None, manual=True, commit=True):
    where = (env.mogrify('%s = ANY(labels)', [folder]) if folder else
             env.mogrify('labels && %s::varchar[]', [list(FOLDERS)]))
    emails = env.sql('''
    SELECT
        id, fr, sender, "to", cc, subj, labels,
        array_prepend(in_reply_to, refs) AS refs
    FROM emails WHERE thrid IS NULL AND {where} ORDER BY id
    '''.format(where=where)).fetchall()
    log.info('  * Update thread ids for %s emails', len(emails))

    def yet(condition):
        if thrid and pid:
            return False
        return condition

    t, updated = Timer(), []
    for row in emails:
        thrid = pid = None

        refs = [r for r in row['refs'] if r]
        ctx = {'folder': folder or (set(FOLDERS) & set(row['labels'])).pop()}

        m_label = [l for l in row['labels'] if l.startswith('%s/' % THRID)]
        if manual and m_label:
            # Manual thread
            extid = m_label.pop().replace('%s/' % THRID, '')
            thrid = env.sql(
                '''
            SELECT id FROM emails
            WHERE extid=%(extid)s AND %(folder)s = ANY(labels)
            ''', dict(ctx, extid=extid)).fetchone()
            if thrid:
                thrid = thrid[0]

        if yet(row['fr'][0].endswith('<*****@*****.**>')):
            # Failed delivery
            text = env.sql('SELECT text FROM emails WHERE id=%s', [row['id']])
            text = text.fetchone()[0]
            msgid = re.search('(?m)^Message-ID:(.*)$', text)
            if msgid:
                msgid = msgid.group(1).strip()
                parent = env.sql(
                    '''
                SELECT id, thrid FROM emails
                WHERE
                    %(folder)s = ANY(labels)
                    AND msgid=%(msgid)s
                ORDER BY id DESC
                LIMIT 1
                ''', dict(ctx, msgid=msgid)).fetchone()
                if parent:
                    thrid = thrid or parent['thrid']
                    pid = pid or parent['id']

        if yet(refs):
            parent = env.sql(
                '''
            SELECT id, thrid FROM emails
            WHERE
                %(folder)s = ANY(labels)
                AND msgid = %(ref)s
            ORDER BY id DESC
            LIMIT 1
            ''', dict(ctx, ref=refs[0])).fetchone()
            if not parent and refs:
                parent = env.sql(
                    '''
                SELECT id, thrid FROM emails
                WHERE
                    %(folder)s = ANY(labels)
                    AND (in_reply_to || refs) && %(refs)s::varchar[]
                ORDER BY id DESC
                LIMIT 1
                ''', dict(ctx, refs=refs)).fetchone()
            if parent:
                thrid = thrid or parent['thrid']
                pid = pid or parent['id']

        if yet(row['fr'] and row['to']):
            fr = row['sender'][0] if row['sender'] else row['fr'][0]
            fr = parseaddr(fr)[1]
            parent = env.sql(
                '''
            SELECT id, thrid FROM emails
            WHERE
              %(folder)s = ANY(labels)
              AND id < %(id)s
              AND subj LIKE %(subj)s
              AND array_to_string(sender || fr || "to" || cc, ',') LIKE %(fr)s
              AND (sender || fr || "to" || cc) && %(to)s::varchar[]
            ORDER BY id DESC
            LIMIT 1
            ''',
                dict(
                    ctx, **{
                        'subj':
                        '%{}'.format(row['subj']) if row['subj'] else '',
                        'fr': '%<{}>%'.format(fr),
                        'to': row['to'] + row['cc'],
                        'id': row['id'],
                    })).fetchone()
            if parent:
                thrid = thrid or parent['thrid']
                pid = pid or parent['id']

        updates = {'thrid': thrid if thrid else row['id'], 'parent': pid}
        env.emails.update(updates, 'id=%s', [row['id']])
        updated.append(row['id'])

    if updated:
        env.db.commit()
        log.info('  - for %.2fs', t.time())
    return updated