Exemple #1
0
    def _recv_handshake(self, key):
        pending = ''
        while True:
            if pending.find('\r\n\r\n') < 0:
                data = self.sock.recv(_buffer_size)
                logger.debug('received %d bytes\n%s', len(data), data)
                if not data:
                    raise Terminated()
                pending += data

            if pending.find('\r\n\r\n') >= 0:
                data, pending = pending.split('\r\n\r\n', 1)

                firstline, headers = data.split(
                    '\r\n', 1) if data.find('\r\n') >= 0 else (data, '')
                protocol, code, reason = firstline.split(' ', 2)
                if code != '101': raise HTTPError(code + ' ' + reason)

                headers = MIMEMessage(StringIO(headers))
                if headers.get('Upgrade', '').lower() != 'websocket':
                    raise HTTPError('invalid Upgrade header')
                if headers.get('Connection', '').lower() != 'upgrade':
                    raise HTTPError('invalid Connection header')

                accept = headers.get('Sec-WebSocket-Accept', '')
                digest = base64.b64encode(
                    hashlib.sha1(key + _magic).hexdigest().decode('hex'))
                if accept.lower() != digest.lower():
                    raise HTTPError('invalid Sec-WebSocket-Accept header')

                _callit(self, 'onopen', self)
                break
        return pending
Exemple #2
0
 def add_message(self, msg, count):
     """Add the message to the digest."""
     # Make a copy of the message object, since the RFC 1153 processing
     # scrubs out attachments.
     digest_msg = MIMEMessage(deepcopy(msg))
     digest_msg_content = digest_msg.get_payload(0)
     # It would be nice to add Message: n near the beginning, but there's no
     # method for that.  MUAs mostly don't display it anyway, so it doesn't
     # really matter.
     digest_msg_content['Message'] = str(count)
     self._digest_part.attach(digest_msg)
Exemple #3
0
 def __setitem__(self, name, val):
     name, val = to_str(name, self.encoding), to_str(val, self.encoding)
     forbid_multi_line_headers(name, val)
     try:
         val.encode("ascii")
     except UnicodeEncodeError:
         if name.lower() in ADDRESS_HEADERS:
             val = ", ".join(
                 encode_address(addr, self.charset)
                 for addr in getaddresses((val, )))
         else:
             val = self.charset.header_encode(val)
     MIMEMessage.__setitem__(self, name, val)
    def _create_mime_attachment(self, content, mimetype):
        """
        Convert the content, mimetype pair into a MIME attachment object.
        If the mimetype is message/rfc822, content may be an
        email.Message or EmailMessage object, as well as a str.
        """
        basetype, subtype = mimetype.split('/', 1)
        if basetype == 'text':
            encoding = self.encoding
            attachment = MIMEText(content, subtype, encoding)
        elif basetype == 'message' and subtype == 'rfc822':
            # Bug #18967: per RFC2046 s5.2.1, message/rfc822 attachments
            # must not be base64 encoded.
            if isinstance(content, EmailMessage):
                # convert content into an email.Message first
                content = content.message()
            elif not isinstance(content, Message):
                # For compatibility with existing code, parse the message
                # into an email.Message object if it is not one already.
                content = message_from_string(str(content))

            attachment = MIMEMessage(content, subtype)
        else:
            # Encode non-text attachments with base64.
            attachment = MIMEBase(basetype, subtype)
            attachment.set_payload(content)
            encoders.encode_base64(attachment)
        return attachment
Exemple #5
0
 def msg(self):
     if self._msg is None:
         self._msg = MIMEMessage(
             message_from_file(
                 BytesIO('\r\n'.join('{0}: {1}'.format(*h)
                                     for h in self.getheaders()))))
     return self._msg
def dispose(mlist, msg, msgdata, why):
    if mlist.filter_action is FilterAction.reject:
        # Bounce the message to the original author.
        raise RejectMessage(why)
    elif mlist.filter_action is FilterAction.forward:
        # Forward it on to the list moderators.
        text = _("""\
The attached message matched the $mlist.display_name mailing list's content
filtering rules and was prevented from being forwarded on to the list
membership.  You are receiving the only remaining copy of the discarded
message.

""")
        subject = _('Content filter message notification')
        notice = OwnerNotification(mlist, subject, roster=mlist.moderators)
        notice.set_type('multipart/mixed')
        notice.attach(MIMEText(text))
        notice.attach(MIMEMessage(msg))
        notice.send(mlist)
        # Let this fall through so the original message gets discarded.
    elif mlist.filter_action is FilterAction.preserve:
        if as_boolean(config.mailman.filtered_messages_are_preservable):
            # This is just like discarding the message except that a copy is
            # placed in the 'bad' queue should the site administrator want to
            # inspect the message.
            filebase = config.switchboards['bad'].enqueue(msg, msgdata)
            log.info('{} preserved in file base {}'.format(
                msg.get('message-id', 'n/a'), filebase))
    else:
        log.error('{} invalid FilterAction: {}.  Treating as discard'.format(
            mlist.fqdn_listname, mlist.filter_action.name))
    # Most cases also discard the message
    raise DiscardMessage(why)
Exemple #7
0
 def moderate(self, msg):
     # For some reason, this import doesn't work at the file level.
     from control import sign
     message_id = msg['message-id']
     if not message_id:
         print(
             'Unable to moderate incoming message due to lack of Message-ID: header.'
         )
         raise ValueError('Messages must contain a Message-ID: header.')
     message_id = message_id.replace(
         ':', '_')  # Make it safe for subject-command.
     # Put the email message into the list's moderation holding space on S3.
     response = s3.put_object(
         Bucket=config.s3_bucket,
         Key=self._s3_moderation_prefix + message_id,
         Body=msg.as_string(),
     )
     # Get the moderation auto-deletion/auto-rejection interval from the S3 bucket lifecycle configuration.
     lifecycle = s3.get_bucket_lifecycle_configuration(
         Bucket=config.s3_bucket)
     from datetime import timedelta
     mod_interval = timedelta(
         days=next((r['Expiration']['Days']
                    for r in lifecycle.get('Rules', [])
                    if r['Prefix'] == config.s3_moderation_prefix), 3))
     # Wrap the moderated message for inclusion in the notification to mods.
     forward_mime = MIMEMessage(msg)
     control_address = 'lambda@{}'.format(self.host)
     for moderator in self.moderator_addresses:
         # Build up the notification email per-moderator so that we can include
         # pre-signed moderation commands specific to that moderator.
         approve_cmd = sign(
             'list {} mod approve "{}"'.format(self.address, message_id),
             moderator, mod_interval)
         reject_cmd = sign(
             'list {} mod reject "{}"'.format(self.address, message_id),
             moderator, mod_interval)
         message = MIMEMultipart()
         message['Subject'] = 'Message to {} needs approval: {}'.format(
             self.address, approve_cmd)
         message['From'] = control_address
         message['To'] = moderator
         message.attach(
             MIMEText(
                 templates.render('notify_moderators.jinja2',
                                  list_name=self.address,
                                  control_address=control_address,
                                  approve_command=approve_cmd,
                                  reject_command=reject_cmd,
                                  moderation_days=mod_interval.days)))
         message.attach(forward_mime)
         ses.send_raw_email(
             Source=control_address,
             Destinations=[
                 moderator,
             ],
             RawMessage={
                 'Data': message.as_string(),
             },
         )
Exemple #8
0
def wrap_message(mlist, msg, msgdata):
    # Create a wrapper message around the original.
    #
    # There are various headers in msg that we don't want, so we basically
    # make a copy of the message, then delete almost everything and set/copy
    # what we want.
    original_msg = copy.deepcopy(msg)
    for key in msg:
        keep = False
        for keeper in KEEPERS:
            if re.match(keeper, key, re.IGNORECASE):
                keep = True
                break
        if not keep:
            del msg[key]
    msg['MIME-Version'] = '1.0'
    msg['Message-ID'] = make_msgid()
    for key, value in munged_headers(mlist, original_msg, msgdata):
        msg[key] = value
    # Are we including dmarc_wrapped_message_text?
    if len(mlist.dmarc_wrapped_message_text) > 0:
        part1 = MIMEText(wrap(mlist.dmarc_wrapped_message_text), 'plain',
                         mlist.preferred_language.charset)
        part1['Content-Disposition'] = 'inline'
        part2 = MIMEMessage(original_msg)
        part2['Content-Disposition'] = 'inline'
        msg['Content-Type'] = 'multipart/mixed'
        msg.set_payload([part1, part2])
    else:
        msg['Content-Type'] = 'message/rfc822'
        msg['Content-Disposition'] = 'inline'
        msg.set_payload([original_msg])
    return
Exemple #9
0
def bounce_message(mlist, msg, error=None):
    """Bounce the message back to the original author.

    :param mlist: The mailing list that the message was posted to.
    :type mlist: `IMailingList`
    :param msg: The original message.
    :type msg: `email.message.Message`
    :param error: Optional exception causing the bounce.  The exception
        instance must have a `.message` attribute.
    :type error: Exception
    """
    # Bounce a message back to the sender, with an error message if provided
    # in the exception argument.  .sender might be None or the empty string.
    if not msg.sender:
        # We can't bounce the message if we don't know who it's supposed to go
        # to.
        return
    subject = msg.get('subject', _('(no subject)'))
    subject = oneline(subject, mlist.preferred_language.charset)
    if error is None:
        notice = _('[No bounce details are available]')
    else:
        notice = _(error.message)
    # Currently we always craft bounces as MIME messages.
    bmsg = UserNotification(msg.sender, mlist.owner_address, subject,
                            lang=mlist.preferred_language)
    # BAW: Be sure you set the type before trying to attach, or you'll get
    # a MultipartConversionError.
    bmsg.set_type('multipart/mixed')
    txt = MIMEText(notice, _charset=mlist.preferred_language.charset)
    bmsg.attach(txt)
    bmsg.attach(MIMEMessage(msg))
    bmsg.send(mlist)
Exemple #10
0
def main(argv):
    options_parser = SetupOptionParser()
    (options, args) = options_parser.parse_args()
    if options.version:
        print '%s %s' % (__program_name, __version__)
        sys.exit(0)
    if options.mail_file:
        f = open(options.mail_file, 'rb')
        original_message = f.read()
        f.close()
    else:
        original_message = gen_random_email(options.days_ago)
    headers = Parser().parsestr(original_message)
    if headers.get_all('x-ms-journal-report') != None:
        print 'refusing to journal a journal message.'
        sys.exit(0)
    from_address = email.utils.getaddresses(headers.get_all('from', []))[0][1]
    if from_address[:4] == 'root@':
        print 'refusing to journal root message'
        sys.exit(0)
    subject = headers.get_all('subject', [])[0]
    #to_emails = email.utils.getaddresses(headers.get_all('to', []))
    to_field_entry = ''
    #for to_email in to_emails:
    #  to_field_entry += "To: %s\r\n" % to_email[1]
    for recipient in options.recipients:
        to_field_entry += "To: %s\r\n" % recipient
    journal_message = MIMEMultipart()
    journal_message['From'] = '<%s>' % options.journal_from_address
    journal_message['To'] = '<%s>' % options.journal_address
    journal_message['Message-ID'] = "<*****@*****.**>" % (
        rand_email_part(), rand_email_part(), rand_email_part())
    journal_message['Subject'] = headers['Subject']
    journal_message['Date'] = email.utils.formatdate()
    journal_message['X-MS-Journal-Report'] = ''
    envelope_part = '''Sender: %s
Subject: %s
Message-Id: %s
%s''' % (from_address, subject, headers['Message-Id'], to_field_entry)
    journal_message.attach(MIMEText(envelope_part, 'plain'))
    journal_message.attach(MIMEMessage(headers, 'rfc822'))
    retries = 5
    for i in range(retries):
        try:
            s = smtplib.SMTP(options.smtp_server)
            s.starttls()
            if options.debug:
                print journal_message
                s.set_debuglevel(1)
            s.sendmail(options.journal_from_address, options.journal_address,
                       journal_message.as_string())
            s.quit()
            break
        except smtplib.SMTPServerDisconnected, e:
            if i + 1 == retries:
                sys.exit(1)
            wait_on_fail = 2**i if 2**i < 60 else 60
            print u'Error: %s. Sleeping %s...' % (e, wait_on_fail)
            time.sleep(wait_on_fail)
Exemple #11
0
def send_probe(member, msg):
    """Send a VERP probe to the member.

    :param member: The member to send the probe to.  From this object, both
        the user and the mailing list can be determined.
    :type member: IMember
    :param msg: The bouncing message that caused the probe to be sent.
    :type msg:
    :return: The token representing this probe in the pendings database.
    :rtype: string
    """
    mlist = getUtility(IListManager).get_by_list_id(
        member.mailing_list.list_id)
    text = make(
        'probe.txt',
        mlist,
        member.preferred_language.code,
        listname=mlist.fqdn_listname,
        address=member.address.email,
        optionsurl=member.options_url,
        owneraddr=mlist.owner_address,
    )
    message_id = msg['message-id']
    if isinstance(message_id, bytes):
        message_id = message_id.decode('ascii')
    pendable = _ProbePendable(
        # We can only pend unicodes.
        member_id=member.member_id.hex,
        message_id=message_id,
    )
    token = getUtility(IPendings).add(pendable)
    mailbox, domain_parts = split_email(mlist.bounces_address)
    probe_sender = Template(config.mta.verp_probe_format).safe_substitute(
        bounces=mailbox,
        token=token,
        domain=DOT.join(domain_parts),
    )
    # Calculate the Subject header, in the member's preferred language.
    with _.using(member.preferred_language.code):
        subject = _('$mlist.display_name mailing list probe message')
    # Craft the probe message.  This will be a multipart where the first part
    # is the probe text and the second part is the message that caused this
    # probe to be sent.
    probe = UserNotification(member.address.email,
                             probe_sender,
                             subject,
                             lang=member.preferred_language)
    probe.set_type('multipart/mixed')
    notice = MIMEText(text, _charset=mlist.preferred_language.charset)
    probe.attach(notice)
    probe.attach(MIMEMessage(msg))
    # Probes should not have the Precedence: bulk header.
    probe.send(mlist,
               envsender=probe_sender,
               verp=False,
               probe_token=token,
               add_precedence=False)
    return token
Exemple #12
0
    def bounce(self, err='Error!', recipient=None):
        """Generate a bounce message with the given error message."""
        text = _('email_text') % err
        html = _('email_html') % err

        self._msg.attach(MIMEText(text, 'plain', 'utf-8'))
        self._msg.attach(MIMEText(html, 'html', 'utf-8'))

        # Stick it all in an envelope.
        envelope = MIMEMultipart('mixed')
        envelope.attach(self._msg)

        # If present, attach the entire incoming email.
        if self._incoming is not None:
            inc_msg = MIMEMessage(self._incoming)
            inc_msg.add_header('Content-Disposition', 'attachment',
                               filename='%s.eml' % self._incoming['subject'])
            envelope.attach(inc_msg)

        if recipient is None and self._incoming:
            recipient = self._incoming.get('reply-to',
                                           self._incoming.get('from'))

        envelope['From'] = settings.MAILTOFAX_EMAIL
        envelope['To'] = recipient
        envelope['Subject'] = _('subject') % (self._incoming['subject'] if
                                              self._incoming else '')
        if self._incoming:
            envelope['In-Reply-To'] = self._incoming['message-id']

        #print self._msg.as_string()
        smtp = smtplib.SMTP(settings.SMTP_SERVER['host'],
                            settings.SMTP_SERVER.get('port') or 25)
        if settings.SMTP_SERVER.get('tls'):
            smtp.starttls()
        if settings.SMTP_SERVER.get('user'):
            smtp.login(settings.SMTP_SERVER['user'],
                       settings.SMTP_SERVER['password'])

        smtp.sendmail(envelope['From'], [envelope['To']],
                      envelope.as_string())
        sys.exit(1)
Exemple #13
0
    def buildMessageFromEmail(self, mail):
        # Create MIMEtext object from email message
        self.fullMsg = MIMEMessage(mail)
        # Parse email message
        self.inMsg = mail
        self.sendAddr = self.inMsg['from']
        self.destAddr = self.inMsg['to']
        self.subject = self.inMsg['subject']

        self.body = self.inMsg.get_payload()
        self.bodyParts = self.body
        self.subjectParts = self.subject.split()

        return self
Exemple #14
0
def send_process_error_notification(to_address, subject, error_msg,
                                    original_msg, failing_command=None,
                                    max_return_size=MAX_RETURN_MESSAGE_SIZE):
    """Send a mail about an error occurring while using the email interface.

    Tells the user that an error was encountered while processing their
    request and attaches the original email which caused the error to
    happen.  The original message will be truncated to
    max_return_size bytes.

        :to_address: The address to send the notification to.
        :subject: The subject of the notification.
        :error_msg: The error message that explains the error.
        :original_msg: The original message sent by the user.
        :failing_command: The command that caused the error to happen.
        :max_return_size: The maximum size returned for the original message.
    """
    if isinstance(failing_command, list):
        failing_commands = failing_command
    elif failing_command is None:
        failing_commands = []
    else:
        failing_commands = [failing_command]
    failed_commands_information = ''
    if len(failing_commands) > 0:
        failed_commands_information = 'Failing command:'
        for failing_command in failing_commands:
            failed_commands_information += '\n    %s' % str(failing_command)

    body = get_email_template(
        'email-processing-error.txt', app='services/mail') % {
            'failed_command_information': failed_commands_information,
            'error_msg': error_msg}
    mailwrapper = MailWrapper(width=72)
    body = mailwrapper.format(body)
    error_part = MIMEText(body.encode('utf-8'), 'plain', 'utf-8')

    msg = MIMEMultipart()
    msg['To'] = to_address
    msg['From'] = get_bugmail_error_address()
    msg['Subject'] = subject
    msg.attach(error_part)
    original_msg_str = str(original_msg)
    if len(original_msg_str) > max_return_size:
        truncated_msg_str = original_msg_str[:max_return_size]
        original_msg = message_from_string(truncated_msg_str)
    msg.attach(MIMEMessage(original_msg))
    sendmail(msg)
Exemple #15
0
def main(args):
  msg1 = Message()
  msg1.set_charset('iso-2022-jp')
  msg1['From'] = Header(u'Yusuke Shinyama <*****@*****.**>', 'iso-2022-jp')
  msg1['To'] = Header(u'きょうから明日です <today@tomorrow>', 'iso-2022-jp')
  msg1['Subject'] = Header(u'ムーミン谷のみなさんへ', 'iso-2022-jp')
  msg1['Date'] = 'Thu, 31 Aug 2004 03:06:09 +0900'
  msg1.set_payload(u'その逆だ!'.encode('iso-2022-jp'), 'iso-2022-jp')
  fp = file(args.pop(0), 'wb')
  fp.write(msg1.as_string(0))
  fp.close()

  msg2 = MIMEMultipart()
  msg2.set_charset('utf-8')
  msg2['From'] = Header(u'えうすけ <*****@*****.**>', 'iso-2022-jp')
  msg2['To'] = Header(u'だれでも <any@one>', 'utf-8')
  msg2['Subject'] = Header(u'何を見てるんだい?', 'iso-2022-jp')
  msg2['Date'] = 'Thu, 29 Feb 2004 19:23:34 +0500'
  text1 = MIMEText(u'ああそうか、\nこれは夢なんだ。'.encode('utf-8'), 'plain', 'utf-8')
  text2 = MIMEText(u'<html><body>\n<strong>HEY!</strong>\n<p>do you wanna feel unconfortably energetic?\n</body></html>', 'html')
  h = Header(u'ふうばあ ばず', 'iso-2022-jp')
  text2.add_header('Content-Disposition', 'attachment', filename=h.encode())
  msg2.set_payload([text1, text2])
  fp = file(args.pop(0), 'wb')
  fp.write(msg2.as_string(0))
  fp.close()

  msg3 = MIMEMultipart()
  msg3['From'] = '=?iso-2022-jp?b?Gy?= \xff\xaa\x88'
  msg3['Subject'] = 'huh?'
  msg3['Date'] = 'Tue, 25 Nov 2008 01:00:09 +0900'
  parts = MIMEMultipart()
  parts.set_payload([MIMEText('part1'), MIMEText('part2')])
  msg4 = Message()
  msg4.set_charset('iso-2022-jp')
  msg4['From'] = Header(u'john doe <*****@*****.**>', 'iso-2022-jp')
  msg4['To'] = Header(u'どこだって? <where@where>', 'iso-2022-jp')
  msg4['Subject'] = Header(u'その先の日本へ', 'iso-2022-jp')
  msg4['Date'] = 'Sun, 31 Aug 2008 12:20:33 +0900'
  msg4.set_payload(u'ししかばう゛ー'.encode('iso-2022-jp'), 'iso-2022-jp')
  msg3.set_payload([parts, MIMEMessage(msg4)])
  fp = file(args.pop(0), 'wb')
  fp.write(msg3.as_string(0))
  fp.close()

  return
def forward_mail(mail: Email,
                 rule: ForwardingRule,
                 server_conn: smtplib.SMTP,
                 save_ids: bool = True):
    logger.info("Sending mail {mail}".format(mail=mail))

    part1 = MIMEText("")
    part2 = MIMEMessage(mail.email)

    new_email = MIMEMultipart()
    new_email['Subject'] = mail.subject
    new_email['From'] = rule.from_address
    new_email['To'] = rule.to_address
    if rule.set_reply_to:
        new_email['Reply-To'] = mail.from_address
    new_email.attach(part1)
    new_email.attach(part2)
    server_conn.send_message(new_email)
    logger.info("Successfully sent mail {mail}".format(mail=mail))
Exemple #17
0
    def reply_to_email(self, og_email, body_text="Got it!"):
        # http://stackoverflow.com/questions/64505/sending-mail-from-python-using-smtp
        new = MIMEMultipart("mixed")
        body = MIMEMultipart("alternative")
        body.attach(MIMEText(body_text, "plain"))
        # body.attach( MIMEText("<html>reply body text</html>", "html") )
        new.attach(body)

        new["Message-ID"] = email.utils.make_msgid()
        new["In-Reply-To"] = og_email["Message-ID"]
        new["References"] = og_email["Message-ID"]
        new["Subject"] = "Re: " + og_email["Subject"]
        new["To"] = og_email["Reply-To"] or og_email["From"]
        new["From"] = self.EMAIL_ADDRESS

        new.attach(MIMEMessage(og_email))
        # print "replying...",
        self.sendserver.sendmail(self.EMAIL_ADDRESS, [new["To"]],
                                 new.as_string())
Exemple #18
0
    def replyMail(self, mId, newBody="", fileNameList=None):
        """
        bu method belirli bir maile cevap vermeyi sağlar
        cevap verileceği için mailin konusu bellidir, başına Re: ekleriz
        NOTE:
            öncesinde readMail() methodunu kullanarak mail id'sini
            öğrenebiliriz

        ARGS:
            :param mId: (string) cevap verilmek istenen mailin id'si
            :param newBody: (string) maile verilecek cevap
            :param fileNameList: (list) eklenecek dosyaların yollarının listesi
            :return: yok
        """
        self.imapper.select(readonly=True)
        type, data = self.imapper.fetch(mId, '(RFC822)')
        original = email.message_from_string(data[0][1])
        # gelen mailin çekilmesi, original--> gönderilecek mail
        new = MIMEMultipart("mixed")
        body = MIMEMultipart("alternative")
        body.attach(MIMEText(newBody, "plain"))
        if fileNameList is not None:
            # varsa gönderilmek istenen dosyalar
            for f in fileNameList:
                attachment = open(f, "rb")
                part = MIMEBase('application', 'octet-stream')
                part.set_payload(attachment.read())
                encoders.encode_base64(part)
                part.add_header('Content-Disposition',
                                "attachment; filename= %s" % f)
                body.attach(part)
        new.attach(body)
        new["Message-ID"] = email.utils.make_msgid()
        new["In-Reply-To"] = original["Message-ID"]
        new["References"] = original["Message-ID"]
        new["Subject"] = "Re: " + original["Subject"]
        new["To"] = original["Reply-To"] or original['From']
        new["From"] = self.emailAddrs
        # yukarıda cevaplamak için mail oluşturdum
        new.attach(MIMEMessage(original))
        # cevaplamak istediğim maili yeni maile ekledim
        self.sendMail(new['To'], new)
Exemple #19
0
    def forwardMail(self, mId, toAddress, newBody="", fileNameList=None):
        """
        Mail id'si ve kime gönderileceği bilinen bir maili
        o kişiye yönlendirmek için method
        :param mId: mailin id'si
        :param toAddress: mail kime yönlendirilecek
        :param newBody: mailin yönlendirileceği kişiye eklenecek body
        :param fileNameList: yönlendirilecek kişiye, varsa eklenecek dosyalar listesi
        :return:

        """
        self.imapper.select(readonly=True)
        type, data = self.imapper.fetch(mId, '(RFC822)')
        original = email.message_from_string(data[0][1])
        # gelen mailin çekilmesi, original--> yönlendirilecek mail
        new = MIMEMultipart("mixed")
        body = MIMEMultipart("alternative")
        body.attach(MIMEText(newBody, "plain"))
        if fileNameList is not None:
            # varsa gönderilmek istenen dosyalar
            for f in fileNameList:
                attachment = open(
                    f, "rb"
                )  # her eklenecek belge aynı klasörde tutulmalı ve belgelerin tutulduğu path gösterilmeli
                part = MIMEBase('application', 'octet-stream')
                part.set_payload(attachment.read())
                encoders.encode_base64(part)
                part.add_header('Content-Disposition',
                                "attachment; filename= %s" % f)
                body.attach(part)
        new.attach(body)
        new["Message-ID"] = email.utils.make_msgid()
        new["In-Reply-To"] = original["Message-ID"]
        new["References"] = original["Message-ID"]
        new["Subject"] = "Fwd:" and original["Subject"]
        new["To"] = toAddress
        new["From"] = self.emailAddrs
        # yukarıda yönlendirmek için mail oluşturdum
        new.attach(MIMEMessage(original))
        # yönlendirmek istediğim maili yeni maile ekledim
        self.sendMail(toAddress, new)
def write_mime_message_payloads(
    output_dir: str,
    transaction_id: str,
    msg: MIMEMessage,
):
    """For each payload in the MIME message, write out the ones that are
    attached as files.

    Args:
        msg (MIMEMessage): The parsed MIME message.
        transaction_id (str): The transaction ID of the email.
        output_dir (str): The directory to write the payloads in.
    """
    for part in msg.walk():
        if is_html(part) and not is_file(part):
            write_html(output_dir, transaction_id, part)

            # for some reason, outlook doesn't like EML files with HTML in them,
            # so we blank out the HTML payload here to display it correctly
            part.set_payload("")
        elif is_file(part) and not part.is_multipart():
            write_attachment(output_dir, transaction_id, part)
Exemple #21
0
def enviar(text, orig):
    try:
        msgid = orig['Message-Id']
        de = settings.get("notificar_errors_from")
        a = settings.get("notificar_errors_to")
        host = settings.get("servidor_mail")
        subject = "Informe d'errors de MailToTicket"
        msg = MIMEMultipart('mixed')
        msg['Subject'] = subject
        msg['From'] = de
        msg['To'] = a
        part1 = MIMEText(text, 'plain', 'utf8')
        part2 = MIMEMessage(orig, 'rfc822')
        msg.attach(part1)
        msg.attach(part2)
        server = smtplib.SMTP(host, 25)
        server.sendmail(de, a, msg.as_string())
        server.quit()
        logger.info("Informe d'errors de %s enviat per correu" % msgid)
    except Exception as e:
        logger.info(e)
        logger.info(
            "No s'ha pogut enviar per correu l'informe d'errors de %s" % msgid)
Exemple #22
0
    def compose_reply(self, reply_data_dir, reply_prefix='RE: '):
        """
        Put everything together into a nice reply email
        """
        assert isinstance(self.reply_to, list)

        rply = MIMEMultipart()
        rply['From'] = self.to
        rply['To'] = COMMASPACE.join(self.reply_to)
        rply['Date'] = formatdate(localtime=True)
        # rply['Date'] = datetime.datetime.today().isoformat()
        rply['Subject'] = reply_prefix + self.subject
        rply["In-Reply-To"] = self.message_id
        rply["References"] = self.message_id
        if self.html:
            rply.attach(MIMEText(self.reply_message, 'html', 'utf-8'))
        else:
            rply.attach(MIMEText(self.reply_message, 'plain', 'utf-8'))

        # import pdb; pdb.set_trace()
        # orig_msg = MIMEMessage(self.raw_message)
        rply.attach(MIMEMessage(self.raw_message))

        if self.attachments:
            files = chain(
                *[_find_files(f, reply_data_dir) for f in self.attachments])

            for f in files:
                print('Attaching: ' + f)
                with open(f, "rb") as fcon:
                    p = MIMEApplication(fcon.read(), Name=basename(f))
                    # After the file is closed
                    p['Content-Disposition'] = 'attachment; filename="%s"' \
                                                              % basename(f)
                    rply.attach(p)

        return rply
Exemple #23
0
def bounce_message(mlist, msg, error=None):
    """Bounce the message back to the original author.

    :param mlist: The mailing list that the message was posted to.
    :type mlist: `IMailingList`
    :param msg: The original message.
    :type msg: `email.message.Message`
    :param error: Optional exception causing the bounce.  The exception
        instance must have a `.message` attribute.  The exception *may* have a
        non-None `.reasons` attribute which would be a list of reasons for the
        rejection, and it may have a non-None `.substitutions` attribute.  The
        latter, along with the formatted reasons will be interpolated into the
        message (`.reasons` gets put into the `$reasons` placeholder).
    :type error: RejectMessage
    """
    # Bounce a message back to the sender, with an error message if provided
    # in the exception argument.  .sender might be None or the empty string.
    if not msg.sender:
        # We can't bounce the message if we don't know who it's supposed to go
        # to.
        return
    subject = msg.get('subject', _('(no subject)'))
    subject = oneline(subject, mlist.preferred_language.charset)
    notice = (_('[No bounce details are available]')
              if error is None else str(error))
    # Currently we always craft bounces as MIME messages.
    bmsg = UserNotification(msg.sender,
                            mlist.owner_address,
                            subject,
                            lang=mlist.preferred_language)
    # BAW: Be sure you set the type before trying to attach, or you'll get
    # a MultipartConversionError.
    bmsg.set_type('multipart/mixed')
    txt = MIMEText(notice, _charset=mlist.preferred_language.charset)
    bmsg.attach(txt)
    bmsg.attach(MIMEMessage(msg))
    bmsg.send(mlist)
Exemple #24
0
def maybe_forward(mlist, msg):
    """Possibly forward bounce messages with no recognizable addresses.

    :param mlist: The mailing list.
    :type mlist: `IMailingList`
    :param msg: The bounce message to scan.
    :type msg: `Message`
    """
    message_id = msg['message-id']
    if (mlist.forward_unrecognized_bounces_to is
            UnrecognizedBounceDisposition.discard):
        blog.error('Discarding unrecognized bounce: {0}'.format(message_id))
        return
    # The notification is either going to go to the list's administrators
    # (owners and moderators), or to the site administrators.  Most of the
    # notification is exactly the same in either case.
    subject = _('Uncaught bounce notification')
    template = getUtility(ITemplateLoader).get(
        'list:admin:notice:unrecognized', mlist)
    text = expand(template, mlist)
    text_part = MIMEText(text, _charset=mlist.preferred_language.charset)
    attachment = MIMEMessage(msg)
    if (mlist.forward_unrecognized_bounces_to is
            UnrecognizedBounceDisposition.administrators):
        keywords = dict(roster=mlist.administrators)
    elif (mlist.forward_unrecognized_bounces_to is
          UnrecognizedBounceDisposition.site_owner):
        keywords = {}
    else:
        raise AssertionError('Invalid forwarding disposition: {0}'.format(
            mlist.forward_unrecognized_bounces_to))
    # Create the notification and send it.
    notice = OwnerNotification(mlist, subject, **keywords)
    notice.set_type('multipart/mixed')
    notice.attach(text_part)
    notice.attach(attachment)
    notice.send(mlist)
Exemple #25
0
	def on_ok(self):
		rv, data = conn.search(None, '(HEADER Message-ID "%s")' % searchtool.replace("\n", ""))
		num = data[0].split()
		rv, data = conn.fetch(num[0], '(RFC822)')
		original = email.message_from_string(data[0][1])
		with open(home + "/.DYGIdep/DEBUG.txt", "w") as f:
			f.write(str(original))
		f.close()
		new = MIMEMultipart("mixed")
		body = MIMEMultipart("alternative")
		body.attach( MIMEText(message2.value, "plain", "utf-8") )
		new.attach(body)
		new["Message-ID"] = email.utils.make_msgid()
		new["In-Reply-To"] = original["Message-ID"]
		new["References"] = original["Message-ID"]
		if new["Subject"] == None:
		    new["Subject"] == "Re: No Subject"
		else:
		    new["Subject"] = "Re: "+ original["Subject"]
		new["To"] = original["Reply-To"] or original["From"]
		new["From"] = gmail.value
		new.attach( MIMEMessage(original) )
		server.sendmail(gmail.value, [new["To"]], new.as_string())
		npyscreen.notify_confirm("Your message has been sent successfully!", title= 'Sent')
def anonymise_mime_message(msg: MIMEMessage) -> MIMEMessage:
    """Replace all of the sensitive fields in the MIME message with messages
    indicating that this message has been anonymised.

    The fields that get replaced are "Subject", "Thread-Topic", as well as the
    body of the email. Attachments are preserved.
    """
    msg.replace_header("Subject", "The subject has been removed for anonymity")

    # the thread topic isn't always present
    if msg.get("Thread-Topic") is not None:
        msg.replace_header("Thread-Topic",
                           "The topic has been removed for anonymity")

    for part in msg.walk():
        # the only parts that contain the body are text/html and text/plain
        # TODO(sam): I think sometimes these can be encoded as base64?
        #            Might need special handling...
        if part.get_content_type() == "text/html" \
                or part.get_content_type() == "text/plain":
            if not is_file(part):
                part.set_payload("The body has been removed for anonymity")

    return msg
Exemple #27
0
 def __setitem__(self, name, val):
     # message/rfc822 attachments must be ASCII
     name, val = forbid_multi_line_headers(name, val, 'ascii')
     MIMEMessage.__setitem__(self, name, val)
Exemple #28
0
    def create(self):
        """
        Create an auto response object from whole cloth.

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

        In most cases, the object will look like:

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

    message = MIMEMultipart('mixed')
    bodypart = _MIMEText_wrapper(body)
    bodypart.add_header('Content-Disposition', 'inline')
    message.preamble = 'This is a multi-part MIME message sent by reportbug.\n\n'
    message.epilogue = ''
    message.attach(bodypart)
    failed = False
    for attachment in attachments:
        try:
            fp = open(attachment)
            fp.close()
        except EnvironmentError as x:
            ewrite(_("Warning: opening '%s' failed: %s.\n"), attachment,
                   x.strerror)
            failed = True
            continue
        ctype = None
        cset = charset
        info = Popen(
            ['file', '--mime', '--brief', '--dereference', attachment],
            stdout=PIPE,
            stderr=STDOUT).communicate()[0].decode('ascii')
        if info:
            match = re.match(r'([^;, ]*)(,[^;]+)?(?:; )?(.*)', info)
            if match:
                ctype, junk, extras = match.groups()
                match = re.search(r'charset=([^,]+|"[^,"]+")', extras)
                if match:
                    cset = match.group(1)
                # If we didn't get a real MIME type, fall back
                if '/' not in ctype:
                    ctype = None
        # If file doesn't work, try to guess based on the extension
        if not ctype:
            ctype, encoding = mimetypes.guess_type(attachment, strict=False)
        if not ctype:
            ctype = 'application/octet-stream'

        maintype, subtype = ctype.split('/', 1)
        if maintype == 'text':
            try:
                with open(attachment, 'rU') as fp:
                    part = _MIMEText_wrapper(fp.read())
            except UnicodeDecodeError:
                fp = open(attachment, 'rb')
                part = MIMEBase(maintype, subtype)
                part.set_payload(fp.read())
                fp.close()
                email.encoders.encode_base64(part)
        elif maintype == 'message':
            fp = open(attachment, 'rb')
            part = MIMEMessage(email.message_from_file(fp), _subtype=subtype)
            fp.close()
        elif maintype == 'image':
            fp = open(attachment, 'rb')
            part = MIMEImage(fp.read(), _subtype=subtype)
            fp.close()
        elif maintype == 'audio':
            fp = open(attachment, 'rb')
            part = MIMEAudio(fp.read(), _subtype=subtype)
            fp.close()
        else:
            fp = open(attachment, 'rb')
            part = MIMEBase(maintype, subtype)
            part.set_payload(fp.read())
            fp.close()
            email.encoders.encode_base64(part)
        part.add_header('Content-Disposition',
                        'attachment',
                        filename=os.path.basename(attachment))
        message.attach(part)
    return (message, failed)
Exemple #30
0
 def __setitem__(self, name, val):
     # message/rfc822 attachments must be ASCII
     name, val = forbid_multi_line_headers(name, val, 'ascii')
     MIMEMessage.__setitem__(self, name, val)
Exemple #31
0
    def _process(self, mlist, msg, msgdata):
        """See `TerminalChainBase`."""
        # Start by decorating the message with a header that contains a list
        # of all the rules that matched.  These metadata could be None or an
        # empty list.
        rule_hits = msgdata.get('rule_hits')
        if rule_hits:
            msg['X-Mailman-Rule-Hits'] = SEMISPACE.join(rule_hits)
        rule_misses = msgdata.get('rule_misses')
        if rule_misses:
            msg['X-Mailman-Rule-Misses'] = SEMISPACE.join(rule_misses)
        # Hold the message by adding it to the list's request database.
        request_id = hold_message(mlist, msg, msgdata, None)
        # Calculate a confirmation token to send to the author of the
        # message.
        pendable = HeldMessagePendable(id=request_id)
        token = getUtility(IPendings).add(pendable)
        # Get the language to send the response in.  If the sender is a
        # member, then send it in the member's language, otherwise send it in
        # the mailing list's preferred language.
        member = mlist.members.get_member(msg.sender)
        language = (member.preferred_language
                    if member else mlist.preferred_language)
        # A substitution dictionary for the email templates.
        charset = mlist.preferred_language.charset
        original_subject = msg.get('subject')
        if original_subject is None:
            original_subject = _('(no subject)')
        else:
            # This must be encoded to the mailing list's perferred charset,
            # ignoring incompatible characters, otherwise when creating the
            # notification messages, we could get a Unicode error.
            oneline_subject = oneline(original_subject, in_unicode=True)
            bytes_subject = oneline_subject.encode(charset, 'replace')
            original_subject = bytes_subject.decode(charset)
        substitutions = dict(
            subject=original_subject,
            sender_email=msg.sender,
            reasons=_compose_reasons(msgdata),
            # For backward compatibility.
            sender=msg.sender,
            )
        # At this point the message is held, but now we have to craft at least
        # two responses.  The first will go to the original author of the
        # message and it will contain the token allowing them to approve or
        # discard the message.  The second one will go to the moderators of
        # the mailing list, if the list is so configured.
        #
        # Start by possibly sending a response to the message author.  There
        # are several reasons why we might not go through with this.  If the
        # message was gated from NNTP, the author may not even know about this
        # list, so don't spam them.  If the author specifically requested that
        # acknowledgments not be sent, or if the message was bulk email, then
        # we do not send the response.  It's also possible that either the
        # mailing list, or the author (if they are a member) have been
        # configured to not send such responses.
        if (not msgdata.get('fromusenet') and
                can_acknowledge(msg) and
                mlist.respond_to_post_requests and
                autorespond_to_sender(mlist, msg.sender, language)):
            # We can respond to the sender with a message indicating their
            # posting was held.
            subject = _(
              'Your message to $mlist.fqdn_listname awaits moderator approval')
            send_language_code = msgdata.get('lang', language.code)
            template = getUtility(ITemplateLoader).get(
                'list:user:notice:hold', mlist,
                language=send_language_code)
            text = wrap(expand(template, mlist, dict(
                language=send_language_code,
                **substitutions)))
            adminaddr = mlist.bounces_address
            nmsg = UserNotification(
                msg.sender, adminaddr, subject, text,
                getUtility(ILanguageManager)[send_language_code])
            nmsg.send(mlist)
        # Now the message for the list moderators.  This one should appear to
        # come from <list>-owner since we really don't need to do bounce
        # processing on it.
        if mlist.admin_immed_notify:
            # Now let's temporarily set the language context to that which the
            # administrators are expecting.
            with _.using(mlist.preferred_language.code):
                language = mlist.preferred_language
                charset = language.charset
                substitutions['subject'] = original_subject
                # We need to regenerate or re-translate a few values in the
                # substitution dictionary.
                substitutions['reasons'] = _compose_reasons(msgdata, 55)
                # craft the admin notification message and deliver it
                subject = _(
                    '$mlist.fqdn_listname post from $msg.sender requires '
                    'approval')
                nmsg = UserNotification(mlist.owner_address,
                                        mlist.owner_address,
                                        subject, lang=language)
                nmsg.set_type('multipart/mixed')
                template = getUtility(ITemplateLoader).get(
                    'list:admin:action:post', mlist)
                text = MIMEText(expand(template, mlist, substitutions),
                                _charset=charset)
                dmsg = MIMEText(wrap(_("""\
If you reply to this message, keeping the Subject: header intact, Mailman will
discard the held message.  Do this if the message is spam.  If you reply to
this message and include an Approved: header with the list password in it, the
message will be approved for posting to the list.  The Approved: header can
also appear in the first line of the body of the reply.""")),
                                _charset=language.charset)
                dmsg['Subject'] = 'confirm ' + token
                dmsg['From'] = mlist.request_address
                dmsg['Date'] = formatdate(localtime=True)
                dmsg['Message-ID'] = make_msgid()
                nmsg.attach(text)
                nmsg.attach(MIMEMessage(msg))
                nmsg.attach(MIMEMessage(dmsg))
                nmsg.send(mlist, **dict(tomoderators=True))
        # Log the held message.  Log messages are not translated, so recast
        # the reasons in the English.
        with _.using('en'):
            reasons = msgdata.get('moderation_reasons', ['N/A'])
            log.info('HOLD: %s post from %s held, message-id=%s: %s',
                     mlist.fqdn_listname, msg.sender,
                     msg.get('message-id', 'n/a'), SEMISPACE.join(reasons))
        notify(HoldEvent(mlist, msg, msgdata, self))
Exemple #32
0
 def msg(self):
     if self._msg is None:
         self._msg = MIMEMessage(message_from_headers(self.getheaders()))
     return self._msg
from __future__ import unicode_literals