Example #1
0
    def testNonASCIIAddrs(self):
        import os
        from email.mime import base
        import transaction
        from repoze.sendmail.delivery import QueuedMailDelivery
        from repoze.sendmail._compat import b
        from repoze.sendmail._compat import text_type
        delivery = QueuedMailDelivery(self.maildir_path)

        non_ascii = b('LaPe\xc3\xb1a').decode('utf-8')
        fromaddr = non_ascii + ' <*****@*****.**>'
        toaddrs = (non_ascii + ' <*****@*****.**>', )
        message = base.MIMEBase('text', 'plain')
        message['From'] = fromaddr
        message['To'] = ','.join(toaddrs)

        delivery.send(fromaddr, toaddrs, message)
        self.assertTrue(os.listdir(os.path.join(self.maildir_path, 'tmp')))
        self.assertFalse(os.listdir(os.path.join(self.maildir_path, 'new')))
        transaction.commit()
        self.assertFalse(os.listdir(os.path.join(self.maildir_path, 'tmp')))
        self.assertTrue(os.listdir(os.path.join(self.maildir_path, 'new')))

        self.qp.send_messages()
        self.assertTrue(len(self.qp.mailer.sent_messages), 1)
        queued_fromaddr, queued_toaddrs, queued_message = (
            self.qp.mailer.sent_messages[0])
        self.assertEqual(queued_fromaddr, fromaddr)
        self.assertEqual(queued_toaddrs, toaddrs)
Example #2
0
def attach(filename):
    '''Elkészíti a MIME részt, benne a fájlnévvel'''
    if not os.path.isfile(filename):
        return None

    ctype, encoding = mimetypes.guess_type(filename)
    if ctype is None or encoding is not None:
        ctype = 'application/octet-stream'

    maintype, subtype = ctype.split('/', 1)
    attachContent = open(filename, 'rb').read()

    if maintype == 'text':
        msg = text.MIMEText(attachContent, _subtype=subtype)
    elif maintype == 'image':
        msg = image.MIMEImage(attachContent, _subtype=subtype)
    elif maintype == 'audio':
        msg = audio.MIMEAudio(attachContent, _subtype=subtype)
    else:
        msg = base.MIMEBase(maintype, subtype)
        msg.set_payload(attachContent)
        encoders.encode_base64(msg)

    msg.add_header('Content-Disposition', 'attachment', filename=filename)
    return msg
Example #3
0
def send_mail(config, subject, message, files_to_attach):
    # unpack some config stuff
    email = config["email_config"]["email"]
    password = config["email_config"]["password"]
    email_name = config["email_config"]["name"]
    to_list = config["mailing_list"]["emails"]
    to_list_name = config["mailing_list"]["name"]

    # connect to gmail
    server = smtp('smtp.gmail.com', 587)
    server.ehlo()
    server.starttls()
    server.login(email, password)

    # build up the message
    msg = multipart.MIMEMultipart()
    msg.attach(text.MIMEText(message))
    msg['From'] = email_name
    msg['To'] = to_list_name
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    for f in files_to_attach:
        part = base.MIMEBase('application', "octet-stream")
        with open(f, "rb") as fp:
            part.set_payload(fp.read())
        encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="{0}"'.format(os.path.basename(f)))
        msg.attach(part)

    server.sendmail(email, to_list, msg.as_string())
    server.quit()
Example #4
0
def send_email(message_body,
               subject,
               sender,
               recipients,
               server,
               attachments=[],
               message_body_type='plain'):

    msg_root = mimemultipart.MIMEMultipart('mixed')
    msg_root['Date'] = email.utils.formatdate(localtime=True)
    msg_root['From'] = sender
    msg_root['To'] = ', '.join(recipients)
    msg_root['Subject'] = email.header.Header(subject, 'utf-8')

    msg_txt = mimetext.MIMEText(message_body, message_body_type, 'utf-8')
    msg_root.attach(msg_txt)

    for attachment in attachments:
        filename = os.path.basename(attachment)

        with open(attachment, 'rb') as f:
            msg_attach = mimebase.MIMEBase('application', 'octet-stream')
            msg_attach.set_payload(f.read())
            email.encoders.encode_base64(msg_attach)
            msg_attach.add_header('Content-Disposition',
                                  'attachment',
                                  filename=(email.header.Header(
                                      filename, 'utf-8').encode()))
            msg_root.attach(msg_attach)

    server.send_message(msg_root)
Example #5
0
def mp_userdata_from_files(files, compress=False, multipart_mime=None):
    outer = multipart_mime or multipart.MIMEMultipart()
    mtypes = []
    for i, fp in enumerate(files):
        mtype = _get_type_from_fp(fp)
        mtypes.append(mtype)
        maintype, subtype = mtype.split('/', 1)
        if maintype == 'text':
            # Note: we should handle calculating the charset
            msg = text.MIMEText(fp.read(), _subtype=subtype)
            fp.close()
        else:
            if hasattr(fp, 'name'):
                fp = open(fp.name, 'rb')
            msg = base.MIMEBase(maintype, subtype)
            msg.set_payload(fp.read())
            fp.close()
            # Encode the payload using Base64
            encoders.encode_base64(msg)
        # Set the filename parameter
        fname = getattr(fp, 'name', "sc_%d" % i)
        msg.add_header('Content-Disposition',
                       'attachment',
                       filename=os.path.basename(fname))
        outer.attach(msg)
    userdata = outer.as_string()
    if compress:
        s = StringIO.StringIO()
        gfile = gzip.GzipFile(fileobj=s, mode='w')
        gfile.write(userdata)
        gfile.close()
        s.seek(0)
        userdata = s.read()
    return userdata
    def StoreBlob(self, form_item, creation):
        """Store form-item to blob storage.

    Args:
      form_item: FieldStorage instance that represents a specific form field.
        This instance should have a non-empty filename attribute, meaning that
        it is an uploaded blob rather than a normal form field.
      creation: Timestamp to associate with new blobs creation time.  This
        parameter is provided so that all blobs in the same upload form can have
        the same creation date.

    Returns:
      datastore.Entity('__BlobInfo__') associated with the upload.
    """
        main_type, sub_type = _SplitMIMEType(form_item.type)

        blob_key = self.__generate_blob_key()
        self.__blob_storage.StoreBlob(blob_key, form_item.file)
        content_type_formatter = base.MIMEBase(main_type, sub_type,
                                               **form_item.type_options)

        blob_entity = datastore.Entity('__BlobInfo__', name=str(blob_key))
        blob_entity['content_type'] = (
            content_type_formatter['content-type'].decode('utf-8'))
        blob_entity['creation'] = creation
        blob_entity['filename'] = form_item.filename.decode('utf-8')
        form_item.file.seek(0, 2)
        size = form_item.file.tell()
        form_item.file.seek(0)
        blob_entity['size'] = size
        datastore.Put(blob_entity)
        return blob_entity
Example #7
0
def send_fic(url: str, email_address: str, password: str, kindle_email):
    port = 587
    fic_filename = download_mobi_and_get_file_name(url)
    print('downloaded!')
    email = smtplib.SMTP('smtp.gmail.com', port)
    email.ehlo()
    email.starttls()
    # password = input('Password:'******'From'] = email_address
    msg['To'] = kindle_email
    msg['Subject'] = ''
    attachment = open(fic_filename, 'rb')
    p = base.MIMEBase('application', 'octet-stream')
    p.set_payload(attachment.read())
    encoders.encode_base64(p)
    p.add_header('Content-Disposition',
                 "attachment; filename= %s" % fic_filename)
    msg.attach(p)
    text = msg.as_string()
    email.sendmail(email_address, kindle_email, text)
    print('sent!')
    email.quit()
    attachment.close()
    os.remove(fic_filename)
Example #8
0
def _getbundlemsgs(repo, sender, bundle, **opts):
    """Get the full email for sending a given bundle

    This function returns a list of "email" tuples (subject, content, None).
    The list is always one message long in that case.
    """
    ui = repo.ui
    _charsets = mail._charsets(ui)
    subj = opts.get('subject') or prompt(ui, b'Subject:',
                                         b'A bundle for your repository')

    body = _getdescription(repo, b'', sender, **opts)
    msg = emimemultipart.MIMEMultipart()
    if body:
        msg.attach(mail.mimeencode(ui, body, _charsets, opts.get('test')))
    datapart = emimebase.MIMEBase('application', 'x-mercurial-bundle')
    datapart.set_payload(bundle)
    bundlename = b'%s.hg' % opts.get('bundlename', b'bundle')
    datapart.add_header(
        'Content-Disposition',
        'attachment',
        filename=encoding.strfromlocal(bundlename),
    )
    emailencoders.encode_base64(datapart)
    msg.attach(datapart)
    msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test'))
    return [(msg, subj, None)]
Example #9
0
def Send_email(file_name_list, email_text, recei_list):
    mail_info = {
        "from": "***@***.com",  # 自己的邮箱账号
        "to": "***@***.com",  # 接收邮件的对方账号
        "hostname": "smtp.exmail.qq.com",
        "username": "******",  # 开通smtp服务的邮箱账号
        "password": "******",  # 开通smtp服务的对应密码
        "mail_subject": "test",
        "mail_text": "hello, this is a test email, sended by python",
        "mail_encoding": "utf-8"
    }

    server = smtplib.SMTP_SSL(mail_info["hostname"], port=465)
    server.ehlo(mail_info["hostname"])
    server.login(mail_info["username"], mail_info["password"])  # 仅smtp服务器需要验证时

    # 构造MIMEMultipart对象做为根容器
    main_msg = multipart.MIMEMultipart()
    # 构造MIMEText对象做为邮件显示内容并附加到根容器
    text_msg = text.MIMEText(email_text, _charset="utf-8")
    main_msg.attach(text_msg)

    # 构造MIMEBase对象做为文件附件内容并附加到根容器
    for file_name in file_name_list:
        ## 读入文件内容并格式化 [方式1]
        data = open(file_name, 'rb')
        ctype, encoding = mimetypes.guess_type(file_name)
        if ctype is None or encoding is not None:
            ctype = 'application/octet-stream'
        maintype, subtype = ctype.split('/', 1)
        file_msg = base.MIMEBase(maintype, subtype)
        file_msg.set_payload(data.read())
        data.close()
        email.encoders.encode_base64(file_msg)  # 把附件编码

        ## 设置附件头
        basename = os.path.basename(file_name)
        file_msg.add_header('Content-Disposition',
                            'attachment',
                            filename=basename,
                            encoding='utf-8')
        main_msg.attach(file_msg)
    # 设置根容器属性
    main_msg['From'] = mail_info['from']
    main_msg['To'] = ';'.join(recei_list)
    main_msg['Subject'] = email_text
    main_msg['Date'] = email.utils.formatdate()

    # 得到格式化后的完整文本
    fullText = main_msg.as_string()

    # 用smtp发送邮件
    try:
        server.sendmail(mail_info['from'], recei_list, fullText)
    finally:
        server.quit()
Example #10
0
 def _handle_attachments(cls, outer, attachments):
     if type(attachments) == str:
         attrs = [attachments]
     elif type(attachments) == list:
         attrs = attachments
     else:
         attrs = []
     for attached in attrs:
         if not os.path.isfile(attached):
             logger.warn('attached is not a file:%s' % attached)
             continue
         # Guess the content type based on the file's extension.  Encoding
         # will be ignored, although we should check for simple things like
         # gzip'd or compressed files.
         ctype, encoding = mimetypes.guess_type(attached)
         if ctype is None or encoding is not None:
             # No guess could be made, or the file is encoded (compressed)
             # use a generic bag-of-bits type.
             ctype = 'application/octet-stream'
         maintype, subtype = ctype.split('/', 1)
         try:
             if maintype == 'text':
                 with open(attached, 'rb') as fhandle:
                     # Note: we should handle calculating the charset
                     msg = text.MIMEText(
                         fhandle.read(), _subtype=subtype
                     )
             elif maintype == 'image':
                 with open(attached, 'rb') as fhandle:
                     imgid = os.path.basename(attached)
                     msg = image.MIMEImage(
                         fhandle.read(), _subtype=subtype
                     )
                     msg.add_header('Content-ID', imgid)
             elif maintype == 'audio':
                 with open(attached, 'rb') as fhandle:
                     msg = audio.MIMEAudio(fhandle.read(), _subtype=subtype)
             else:
                 with open(attached, 'rb') as fhandle:
                     msg = base.MIMEBase(maintype, subtype)
                     msg.set_payload(fhandle.read())
                 # Encode the payload using Base64
                 encoders.encode_base64(msg)
                 # Set the filename parameter
             msg.add_header(
                 'Content-Disposition', 'attachment',
                 filename=os.path.basename(attached)
             )
             outer.attach(msg)
         # pylint: disable=W0703
         except Exception as exception:
             logger.warn(
                 'failed to attach %s, errmsg:%s. Will skip it' % (
                     attached, str(exception)
                 )
             )
Example #11
0
  def StoreBlob(self, form_item, creation):
    """Store form-item to blob storage.

    Args:
      form_item: FieldStorage instance that represents a specific form field.
        This instance should have a non-empty filename attribute, meaning that
        it is an uploaded blob rather than a normal form field.
      creation: Timestamp to associate with new blobs creation time.  This
        parameter is provided so that all blobs in the same upload form can have
        the same creation date.

    Returns:
      datastore.Entity('__BlobInfo__') associated with the upload.
    """
    main_type, sub_type = _SplitMIMEType(form_item.type)

    blob_key = self.__generate_blob_key()
    blob_file = form_item.file
    if 'Content-Transfer-Encoding' in form_item.headers:
      if form_item.headers['Content-Transfer-Encoding'] == 'base64':
        blob_file = cStringIO.StringIO(
            base64.urlsafe_b64decode(blob_file.read()))
    self.__blob_storage.StoreBlob(blob_key, blob_file)
    content_type_formatter = base.MIMEBase(main_type, sub_type,
                                           **form_item.type_options)

    blob_entity = datastore.Entity('__BlobInfo__',
                                   name=str(blob_key),
                                   namespace='')
    try:
      blob_entity['content_type'] = (
          content_type_formatter['content-type'].decode('utf-8'))
      blob_entity['creation'] = creation
      blob_entity['filename'] = form_item.filename.decode('utf-8')
    except UnicodeDecodeError:
      raise InvalidMetadataError(
          'The uploaded entity contained invalid UTF-8 metadata. This may be '
          'because the page containing the upload form was served with a '
          'charset other than "utf-8".')

    blob_file.seek(0)
    digester = hashlib.md5()
    while True:
      block = blob_file.read(1 << 20)
      if not block:
        break
      digester.update(block)

    blob_entity['md5_hash'] = digester.hexdigest()
    blob_entity['size'] = blob_file.tell()
    blob_file.seek(0)

    datastore.Put(blob_entity)
    return blob_entity
Example #12
0
def SendNotificationEmail(subject, body, bugreport=None):
    """Sends an email with the specified subject and body.

     Also attach bugreport if bugreport location is provided as argument

  Args:
    subject: Subject of the email.
    body: Body of the email.
    bugreport: If provided, it will be attach to the email.
  """
    if FLAGS.supress_notification_emails:
        logging.info("Email with subject '%s' has been supressed", subject)
        return
    try:
        # Assemble the message to send.
        recpient_address = FLAGS.notification_address
        message = multipart.MIMEMultipart("alternative")
        message["From"] = "Stress Test on %s" % socket.gethostname()
        message["To"] = recpient_address
        message["Subject"] = subject
        message.attach(text.MIMEText(body, "plain"))
        message.attach(text.MIMEText("<pre>%s</pre>" % body, "html"))

        if FLAGS.attach_bugreport and bugreport:
            # buildozer: disable=unused-variable
            ctype, _ = mimetypes.guess_type(bugreport)
            maintype, subtype = ctype.split("/", 1)
            with open(bugreport, "rb") as fp:
                att = base.MIMEBase(maintype, subtype)
                att.set_payload(fp.read())
                encoders.encode_base64(att)
                att.add_header("Content-Disposition",
                               "attachment",
                               filename=bugreport)
                message.attach(att)

        # Send the message from our special account.
        server = smtplib.SMTP_SSL(FLAGS.email_smtp_server,
                                  FLAGS.email_smtp_port)
        server.login(FLAGS.email_sender_address, FLAGS.email_sender_password)
        server.sendmail(FLAGS.email_sender_address, recpient_address,
                        message.as_string())
        server.quit()
        logging.info("Email with subject '%s' has been sent", subject)
    except:  # pylint:disable=bare-except
        logging.exception("Failed to send notification email")
Example #13
0
def add_attachments(email: MIMEMultipart, attachments: list, max_MB: int = 25):
    '''Add the given attachments to the given email, up to the specified maximum size.
    '''
    mime_consumer = {'text': text.MIMEText,
                     'image': image.MIMEImage,
                     'audio': audio.MIMEAudio }

    sz = len(bytes(email))
    added = 0
    count = 0
    for f in attachments:
        print(sz / 1024 / 1024)
        margin = max_MB * 1024 * 1024 - sz
        if margin <= 100000:
            print(f'Message size limit reached. Added first {count} of {len(attachments)}')
            break
        mimetype, encoding = mimetypes.guess_type(f)
        if mimetype is None or encoding is not None:
            mimetype = 'application/octet-stream'
        main_type, sub_type = mimetype.split('/', 1)

        consumer = mime_consumer[main_type] if (main_type in mime_consumer) else (
            application.MIMEApplication if (main_type == 'application' and sub_type == 'pdf') else None
        )
        attachment = None
        if consumer is None:
            # Use the base mimetype
            attachment = base.MIMEBase(main_type, sub_type)
            with open(f, 'rb') as source:
                attachment.set_payload(source.read())
        else:
            # Use the known conversion.
            print(f'Reading file of type {main_type}')
            with open(f, 'rb') as source:
                attachment = consumer(source.read(), _subtype=sub_type)

        encoders.encode_base64(attachment)
        attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(f))
        if len(bytes(attachment)) >= margin:
            margin = 0 # Add your own "skip this file" or "these should be links from Drive" logic.
        else:
            added = len(bytes(attachment))
            sz += added
            count += 1
            email.attach(attachment)
    print(f'Email size is now ~{len(bytes(email)) / 1024 / 1024} MB')
Example #14
0
    def download(self, urls):
        """Faz o download de diários oficiais a partir de urls."""
        intervalo = '{0}/{2} - {1}/{2}'.format(
            self.parâmetros_busca['edicao.dtInicio'],
            self.parâmetros_busca['edicao.dtFim'],
            self.parâmetros_busca['edicao.ano'],
        )
        subject = 'Oi Igor! Nenhum diario foi encontrado nesse intervalo ({}) a partir da busca '
        subject += '"{}" :/. Amanhã procuro novamente!'
        subject = subject.format(intervalo,
                                 self.parâmetros_busca['edicao.txtPesquisa'])

        email = mail.EmailMessage(
            'Consulta Diário {}'.format(intervalo), subject,
            '*****@*****.**',
            [manager[-1] for manager in settings.MANAGERS])
        for index, url in enumerate(urls):
            if index == 0:
                email.body = 'Oi Igor! Foram encontrados diários nesse intervalo ({}) a partir da'
                email.body += ' busca "{}"! :D. Segue em anexo:'
                email.body = email.body.format(
                    intervalo, self.parâmetros_busca['edicao.txtPesquisa'])

            logger.info('Baixando diário a partir da url %s', url)

            diário_pdf = requests.get(url).content

            attachment = base.MIMEBase('application', 'pdf')
            attachment.set_payload(diário_pdf)
            encoders.encode_base64(attachment)

            nome_arquivo = '{}-{}'.format(
                self.parâmetros_busca['edicao.dtInicio'],
                self.parâmetros_busca['edicao.dtFim'])
            nome_arquivo = '[{}][{}]({}).pdf'.format(
                self.parâmetros_busca['edicao.txtPesquisa'], nome_arquivo,
                index).replace('/', '.')
            attachment.add_header('Content-Disposition',
                                  'attachment',
                                  filename=nome_arquivo)

            email.attach(attachment)

        email.send()
Example #15
0
 def send_fic(self, fic : FanficDownloader):
     msg = multipart.MIMEMultipart()
     msg['From'] = self.email_address
     msg['To'] = self.kindle_email_address
     msg['Subject'] = ''
     # msg.attach(text.MIMEText('', 'plain'))
     fic.download_story()
     full_path = fic.file_path + '/' + fic.file_name
     # print(full_path)
     # print(fic.file_name)
     attachment = open(full_path, 'rb')
     p = base.MIMEBase('application', 'octet-stream')
     p.set_payload((attachment).read())
     encoders.encode_base64(p)
     p.add_header('Content-Disposition', "attachment; filename= %s" % fic.file_name)
     msg.attach(p)
     text = msg.as_string()
     self.email.sendmail(self.email_address, self.kindle_email_address, text)
     self.email.quit()
    def StoreBlob(self, form_item, creation):
        """Store form-item to blob storage.

    Args:
      form_item: FieldStorage instance that represents a specific form field.
        This instance should have a non-empty filename attribute, meaning that
        it is an uploaded blob rather than a normal form field.
      creation: Timestamp to associate with new blobs creation time.  This
        parameter is provided so that all blobs in the same upload form can have
        the same creation date.

    Returns:
      datastore.Entity('__BlobInfo__') associated with the upload.
    """
        main_type, sub_type = _SplitMIMEType(form_item["content_type"])

        blob_key = self.__generate_blob_key()
        self.__blob_storage.StoreBlob(blob_key,
                                      cStringIO.StringIO(form_item["body"]))
        content_type_formatter = base.MIMEBase(main_type, sub_type)
        # **form_item.type_options)

        blob_entity = datastore.Entity('__BlobInfo__',
                                       name=str(blob_key),
                                       namespace='')
        try:
            blob_entity['content_type'] = (
                content_type_formatter['content-type'].decode('utf-8'))
            blob_entity['creation'] = creation
            blob_entity['filename'] = form_item["filename"]  #.decode('utf-8')
        except UnicodeDecodeError:
            raise InvalidMetadataError(
                'The uploaded entity contained invalid UTF-8 metadata. This may be '
                'because the page containing the upload form was served with a '
                'charset other than "utf-8".')
        #form_item.file.seek(0, 2)
        #size = form_item.file.tell()
        #form_item.file.seek(0)
        blob_entity['size'] = len(form_item["body"])
        datastore.Put(blob_entity)
        return blob_entity
Example #17
0
def attachment_content(mail_config, subject, files):
    """
    create base class for all the MIME-specific subclasses of Message by email.mime.base.MIMEBase class
    """

    configfile = config.Config(mail_config)
    from_addr = configfile.__get_items__("smtp", "from_addr")
    to_addr = configfile.__get_items__("smtp", "to_addr")
    cc = configfile.__get_items__("smtp", "cc")

    msg = multipart.MIMEMultipart()
    msg['To'] = to_addr
    msg['From'] = from_addr
    msg['Subject'] = subject
    msg['CC'] = cc

    msg.attach(
        text.MIMEText(
            '<html><body><p>send by <a href="http://lfzyx.org">lfzyx</a></p>'
            '</body></html>', 'html', 'utf-8'))

    for file in files:
        with open(file, 'rb') as f:
            stream = base.MIMEBase('application',
                                   'octet-stream',
                                   filename=file)
            stream.add_header('Content-Disposition',
                              'attachment',
                              filename=file)
            stream.add_header('Content-ID', '<0>')
            stream.add_header('X-Attachment-Id', '0')
            stream.set_payload(f.read())
            email.encoders.encode_base64(stream)
            msg.attach(stream)

    smtp_send(mail_config, msg)
Example #18
0
    def attach(self, filename, mime=None, charset=None, content=None):
        """Attach files to this message.

        Example::

            msg.attach("me.png", mime="image/png")

        It also supports fake attachments::

            msg.attach("fake.txt", mime="text/plain", content="gotcha")
        """
        base = os.path.basename(filename)
        if content is None:
            fd = open(filename)
            content = fd.read()
            fd.close()
        elif not isinstance(content, str):
            raise TypeError("Don't know how to attach content: %s" %
                            repr(content))

        part = email_mime_base.MIMEBase("application", "octet-stream")
        part.set_payload(content)
        email_encoders.encode_base64(part)
        part.add_header("Content-Disposition", "attachment", filename=base)

        if mime is not None:
            part.set_type(mime)

        if charset is not None:
            part.set_charset(charset)

        if self.msg is None:
            self.msg = email_mime_multipart.MIMEMultipart()
            self.msg.attach(self.message)

        self.msg.attach(part)
def send_email(email_subject,
               email_body,
               email_sender='',
               email_to='',
               email_cc='',
               email_bcc='',
               files=None):

    # Pulling in the string value of the service key from the parameter
    with open(r'C:\Users\___.json') as f:
        service_account_info = json.loads(f.read())

    # Define which scopes we're trying to access
    SCOPES = ['https://www.googleapis.com/auth/gmail.send']

    # Setting up credentials using the gmail api
    credentials = service_account.Credentials.from_service_account_info(
        service_account_info, scopes=SCOPES)
    # This allows us to assign an alias account to the message so that the messages aren't coming from 'ServiceDriod-8328balh blah blah'
    delegated_credentials = credentials.with_subject(email_sender)
    # 'Building' the service instance using the credentials we've passed
    service = discovery.build(serviceName='gmail',
                              version='v1',
                              credentials=delegated_credentials)

    # Building out the email
    message = multipart.MIMEMultipart()
    message['to'] = email_to
    message['from'] = email_sender
    message['date'] = utils.formatdate(localtime=True)
    message['subject'] = email_subject
    message['cc'] = email_cc
    message['bcc'] = email_bcc
    message.attach(text.MIMEText(email_body, 'plain'))

    for f in files or []:
        f = f.strip(' ')
        mimetype, encoding = mimetypes.guess_type(f)

        # If the extension is not recognized it will return: (None, None)
        # If it's an .mp3, it will return: (audio/mp3, None) (None is for the encoding)
        # For an unrecognized extension we set mimetype to 'application/octet-stream' so it won't return None again.
        if mimetype is None or encoding is not None:
            mimetype = 'application/octet-stream'
        main_type, sub_type = mimetype.split('/', 1)

        # Creating the attachement:
        # This part is used to tell how the file should be read and stored (r, or rb, etc.)
        if main_type == 'text':
            print('text')
            with open(f, 'rb') as outfile:
                attachement = text.MIMEText(outfile.read(), _subtype=sub_type)
        elif main_type == 'image':
            print('image')
            with open(f, 'rb') as outfile:
                attachement = image.MIMEImage(outfile.read(),
                                              _subtype=sub_type)
        elif main_type == 'audio':
            print('audio')
            with open(f, 'rb') as outfile:
                attachement = audio.MIMEAudio(outfile.read(),
                                              _subtype=sub_type)
        elif main_type == 'application' and sub_type == 'pdf':
            with open(f, 'rb') as outfile:
                attachement = application.MIMEApplication(outfile.read(),
                                                          _subtype=sub_type)
        else:
            attachement = base.MIMEBase(main_type, sub_type)
            with open(f, 'rb') as outfile:
                attachement.set_payload(outfile.read())

        encoders.encode_base64(attachement)
        attachement.add_header('Content-Disposition',
                               'attachment',
                               filename=os.path.basename(f))
        message.attach(attachement)

    media_body = http.MediaIoBaseUpload(io.BytesIO(message.as_bytes()),
                                        mimetype='message/rfc822',
                                        resumable=True)
    body_metadata = {}  # no thread, no labels in this example

    try:
        print('Uploading file...')
        response = service.users().messages().send(
            userId='me', body=body_metadata, media_body=media_body).execute()
        print(response)
    except errors.HttpError as error:
        print('An error occurred when sending the email:\n{}'.format(error))
Example #20
0
  def _GenerateMIMEMessage(self,
                           form,
                           boundary=None,
                           max_bytes_per_blob=None,
                           max_bytes_total=None,
                           bucket_name=None):
    """Generate a new post from original form.

    Also responsible for storing blobs in the datastore.

    Args:
      form: Instance of cgi.FieldStorage representing the whole form
        derived from original post data.
      boundary: Boundary to use for resulting form.  Used only in tests so
        that the boundary is always consistent.
      max_bytes_per_blob: The maximum size in bytes that any single blob
        in the form is allowed to be.
      max_bytes_total: The maximum size in bytes that the total of all blobs
        in the form is allowed to be.
      bucket_name: The name of the Google Storage bucket to uplad the file.

    Returns:
      A MIMEMultipart instance representing the new HTTP post which should be
      forwarded to the developers actual CGI handler. DO NOT use the return
      value of this method to generate a string unless you know what you're
      doing and properly handle folding whitespace (from rfc822) properly.

    Raises:
      UploadEntityTooLargeError: The upload exceeds either the
        max_bytes_per_blob or max_bytes_total limits.
      FilenameOrContentTypeTooLargeError: The filename or the content_type of
        the upload is larger than the allowed size for a string type in the
        datastore.
    """
    message = multipart.MIMEMultipart('form-data', boundary)
    for name, value in form.headers.items():
      if name.lower() not in STRIPPED_HEADERS:
        message.add_header(name, value)

    def IterateForm():
      """Flattens form in to single sequence of cgi.FieldStorage instances.

      The resulting cgi.FieldStorage objects are a little bit irregular in
      their structure.  A single name can have mulitple sub-items.  In this
      case, the root FieldStorage object has a list associated with that field
      name.  Otherwise, the root FieldStorage object just refers to a single
      nested instance.

      Lists of FieldStorage instances occur when a form has multiple values
      for the same name.

      Yields:
        cgi.FieldStorage irrespective of their nesting level.
      """


      for key in sorted(form):
        form_item = form[key]
        if isinstance(form_item, list):
          for list_item in form_item:
            yield list_item
        else:
          yield form_item

    creation = self.__now_func()
    total_bytes_uploaded = 0
    created_blobs = []
    upload_too_large = False
    filename_too_large = False
    content_type_too_large = False

    for form_item in IterateForm():








      disposition_parameters = {'name': form_item.name}

      if form_item.filename is None:

        variable = base.MIMEBase('text', 'plain')
        variable.set_payload(form_item.value)
      else:



        if not form_item.filename:
          continue

        disposition_parameters['filename'] = form_item.filename

        main_type, sub_type = _SplitMIMEType(form_item.type)


        form_item.file.seek(0, 2)
        content_length = form_item.file.tell()
        form_item.file.seek(0)

        total_bytes_uploaded += content_length

        if max_bytes_per_blob is not None:
          if max_bytes_per_blob < content_length:
            upload_too_large = True
            break
        if max_bytes_total is not None:
          if max_bytes_total < total_bytes_uploaded:
            upload_too_large = True
            break
        if form_item.filename is not None:
          if MAX_STRING_NAME_LENGTH < len(form_item.filename):
            filename_too_large = True
            break
        if form_item.type is not None:
          if MAX_STRING_NAME_LENGTH < len(form_item.type):
            content_type_too_large = True
            break


        blob_entity = self.StoreBlob(form_item, creation)


        created_blobs.append(blob_entity)

        variable = base.MIMEBase('message',
                                 'external-body',
                                 access_type=blobstore.BLOB_KEY_HEADER,
                                 blob_key=blob_entity.key().name())


        form_item.file.seek(0)
        digester = hashlib.md5()
        while True:
          block = form_item.file.read(1 << 20)
          if not block:
            break
          digester.update(block)

        blob_key = base64.urlsafe_b64encode(digester.hexdigest())
        form_item.file.seek(0)

        external = base.MIMEBase(main_type,
                                 sub_type,
                                 **form_item.type_options)
        headers = dict(form_item.headers)
        headers['Content-Length'] = str(content_length)
        headers[blobstore.UPLOAD_INFO_CREATION_HEADER] = (
            blobstore._format_creation(creation))
        if bucket_name:
          headers[blobstore.CLOUD_STORAGE_OBJECT_HEADER] = (
              '/gs/%s/fake-%s-%s' % (bucket_name, blob_entity.key().name(),
                                     blob_key))
        headers['Content-MD5'] = blob_key
        for key, value in headers.iteritems():
          external.add_header(key, value)


        external_disposition_parameters = dict(disposition_parameters)


        external_disposition_parameters['filename'] = form_item.filename
        if not external.get('Content-Disposition'):
          external.add_header('Content-Disposition',
                              'form-data',
                              **external_disposition_parameters)
        variable.set_payload([external])


      variable.add_header('Content-Disposition',
                          'form-data',
                          **disposition_parameters)
      message.attach(variable)

    if upload_too_large or filename_too_large or content_type_too_large:
      for blob in created_blobs:
        datastore.Delete(blob)
      if upload_too_large:
        raise UploadEntityTooLargeError()
      elif filename_too_large:
        raise FilenameOrContentTypeTooLargeError('filename')
      else:
        raise FilenameOrContentTypeTooLargeError('content-type')

    return message
Example #21
0
def send_i18n_digests(mlist, mboxfp):
    mbox = Mailbox(mboxfp)
    # Prepare common information (first lang/charset)
    lang = mlist.preferred_language
    lcset = Utils.GetCharSet(lang)
    lcset_out = Charset(lcset).output_charset or lcset
    # Common Information (contd)
    realname = mlist.real_name
    volume = mlist.volume
    issue = mlist.next_digest_number
    digestid = _('%(realname)s Digest, Vol %(volume)d, Issue %(issue)d')
    digestsubj = Header(digestid, lcset, header_name='Subject')
    # Set things up for the MIME digest.  Only headers not added by
    # CookHeaders need be added here.
    # Date/Message-ID should be added here also.
    mimemsg = Message.Message()
    mimemsg['Content-Type'] = 'multipart/mixed'
    mimemsg['MIME-Version'] = '1.0'
    mimemsg['From'] = mlist.GetRequestEmail()
    mimemsg['Subject'] = digestsubj
    mimemsg['To'] = mlist.GetListEmail()
    mimemsg['Reply-To'] = mlist.GetListEmail()
    mimemsg['Date'] = formatdate(localtime=1)
    mimemsg['Message-ID'] = Utils.unique_message_id(mlist)
    # Set things up for the rfc1153 digest
    plainmsg = StringIO()
    rfc1153msg = Message.Message()
    rfc1153msg['From'] = mlist.GetRequestEmail()
    rfc1153msg['Subject'] = digestsubj
    rfc1153msg['To'] = mlist.GetListEmail()
    rfc1153msg['Reply-To'] = mlist.GetListEmail()
    rfc1153msg['Date'] = formatdate(localtime=1)
    rfc1153msg['Message-ID'] = Utils.unique_message_id(mlist)
    separator70 = '-' * 70
    separator30 = '-' * 30
    # In the rfc1153 digest, the masthead contains the digest boilerplate plus
    # any digest header.  In the MIME digests, the masthead and digest header
    # are separate MIME subobjects.  In either case, it's the first thing in
    # the digest, and we can calculate it now, so go ahead and add it now.
    mastheadtxt = Utils.maketext(
        'masthead.txt', {
            'real_name': mlist.real_name,
            'got_list_email': mlist.GetListEmail(),
            'got_listinfo_url': mlist.GetScriptURL('listinfo', absolute=1),
            'got_request_email': mlist.GetRequestEmail(),
            'got_owner_email': mlist.GetOwnerEmail(),
        },
        mlist=mlist)
    # MIME
    masthead = text.MIMEText(mastheadtxt, _charset=lcset)
    masthead['Content-Description'] = digestid
    mimemsg.attach(masthead)
    # RFC 1153
    print(mastheadtxt, file=plainmsg)
    print(file=plainmsg)
    # Now add the optional digest header but only if more than whitespace.
    if re.sub('\s', '', mlist.digest_header):
        headertxt = decorate(mlist, mlist.digest_header, _('digest header'))
        # MIME
        header = text.MIMEText(headertxt, _charset=lcset)
        header['Content-Description'] = _('Digest Header')
        mimemsg.attach(header)
        # RFC 1153
        print(headertxt, file=plainmsg)
        print(file=plainmsg)
    # Now we have to cruise through all the messages accumulated in the
    # mailbox file.  We can't add these messages to the plainmsg and mimemsg
    # yet, because we first have to calculate the table of contents
    # (i.e. grok out all the Subjects).  Store the messages in a list until
    # we're ready for them.
    #
    # Meanwhile prepare things for the table of contents
    toc = StringIO()
    print(_("Today's Topics:\n"), file=toc)
    # Now cruise through all the messages in the mailbox of digest messages,
    # building the MIME payload and core of the RFC 1153 digest.  We'll also
    # accumulate Subject: headers and authors for the table-of-contents.
    messages = []
    msgcount = 0
    msg = next(mbox)
    while msg is not None:
        if msg == '':
            # It was an unparseable message
            msg = next(mbox)
            continue
        msgcount += 1
        messages.append(msg)
        # Get the Subject header
        msgsubj = msg.get('subject', _('(no subject)'))
        subject = Utils.oneline(msgsubj, lcset)
        # Don't include the redundant subject prefix in the toc
        mo = re.match('(re:? *)?(%s)' % re.escape(mlist.subject_prefix),
                      subject, re.IGNORECASE)
        if mo:
            subject = subject[:mo.start(2)] + subject[mo.end(2):]
        username = ''
        addresses = getaddresses([Utils.oneline(msg.get('from', ''), lcset)])
        # Take only the first author we find
        if isinstance(addresses, list) and addresses:
            username = addresses[0][0]
            if not username:
                username = addresses[0][1]
        if username:
            username = '******' % username
        # Put count and Wrap the toc subject line
        wrapped = Utils.wrap('%2d. %s' % (msgcount, subject), 65)
        slines = wrapped.split('\n')
        # See if the user's name can fit on the last line
        if len(slines[-1]) + len(username) > 70:
            slines.append(username)
        else:
            slines[-1] += username
        # Add this subject to the accumulating topics
        first = True
        for line in slines:
            if first:
                print(' ', line, file=toc)
                first = False
            else:
                print('     ', line.lstrip(), file=toc)
        # We do not want all the headers of the original message to leak
        # through in the digest messages.  For this phase, we'll leave the
        # same set of headers in both digests, i.e. those required in RFC 1153
        # plus a couple of other useful ones.  We also need to reorder the
        # headers according to RFC 1153.  Later, we'll strip out headers for
        # for the specific MIME or plain digests.
        keeper = {}
        all_keepers = {}
        for header in (mm_cfg.MIME_DIGEST_KEEP_HEADERS +
                       mm_cfg.PLAIN_DIGEST_KEEP_HEADERS):
            all_keepers[header] = True
        all_keepers = list(all_keepers.keys())
        for keep in all_keepers:
            keeper[keep] = msg.get_all(keep, [])
        # Now remove all unkempt headers :)
        for header in list(msg.keys()):
            del msg[header]
        # And add back the kept header in the RFC 1153 designated order
        for keep in all_keepers:
            for field in keeper[keep]:
                msg[keep] = field
        # And a bit of extra stuff
        msg['Message'] = repr(msgcount)
        # Get the next message in the digest mailbox
        msg = next(mbox)
    # Now we're finished with all the messages in the digest.  First do some
    # sanity checking and then on to adding the toc.
    if msgcount == 0:
        # Why did we even get here?
        return
    toctext = to_cset_out(toc.getvalue(), lcset)
    # MIME
    tocpart = text.MIMEText(toctext, _charset=lcset)
    tocpart['Content-Description'] = _(
        "Today's Topics (%(msgcount)d messages)")
    mimemsg.attach(tocpart)
    # RFC 1153
    print(toctext, file=plainmsg)
    print(file=plainmsg)
    # For RFC 1153 digests, we now need the standard separator
    print(separator70, file=plainmsg)
    print(file=plainmsg)
    # Now go through and add each message
    mimedigest = base.MIMEBase('multipart', 'digest')
    mimemsg.attach(mimedigest)
    first = True
    for msg in messages:
        # MIME.  Make a copy of the message object since the rfc1153
        # processing scrubs out attachments.
        mimedigest.attach(message.MIMEMessage(copy.deepcopy(msg)))
        # rfc1153
        if first:
            first = False
        else:
            print(separator30, file=plainmsg)
            print(file=plainmsg)
        # Use Mailman.Handlers.Scrubber.process() to get plain text
        try:
            msg = scrubber(mlist, msg)
        except Errors.DiscardMessage:
            print(_('[Message discarded by content filter]'), file=plainmsg)
            continue
        # Honor the default setting
        for h in mm_cfg.PLAIN_DIGEST_KEEP_HEADERS:
            if msg[h]:
                uh = Utils.wrap('%s: %s' % (h, Utils.oneline(msg[h], lcset)))
                uh = '\n\t'.join(uh.split('\n'))
                print(uh, file=plainmsg)
        print(file=plainmsg)
        # If decoded payload is empty, this may be multipart message.
        # -- just stringfy it.
        payload = msg.get_payload(decode=True) \
                  or msg.as_string().split('\n\n',1)[1]
        mcset = msg.get_content_charset('')
        if mcset and mcset != lcset and mcset != lcset_out:
            try:
                payload = str(payload, mcset,
                              'replace').encode(lcset, 'replace')
            except (UnicodeError, LookupError):
                # TK: Message has something unknown charset.
                #     _out means charset in 'outer world'.
                payload = str(payload, lcset_out,
                              'replace').encode(lcset, 'replace')
        print(payload, file=plainmsg)
        if not payload.endswith('\n'):
            print(file=plainmsg)
    # Now add the footer but only if more than whitespace.
    if re.sub('\s', '', mlist.digest_footer):
        footertxt = decorate(mlist, mlist.digest_footer, _('digest footer'))
        # MIME
        footer = text.MIMEText(footertxt, _charset=lcset)
        footer['Content-Description'] = _('Digest Footer')
        mimemsg.attach(footer)
        # RFC 1153
        # MAS: There is no real place for the digest_footer in an RFC 1153
        # compliant digest, so add it as an additional message with
        # Subject: Digest Footer
        print(separator30, file=plainmsg)
        print(file=plainmsg)
        print('Subject: ' + _('Digest Footer'), file=plainmsg)
        print(file=plainmsg)
        print(footertxt, file=plainmsg)
        print(file=plainmsg)
        print(separator30, file=plainmsg)
        print(file=plainmsg)
    # Do the last bit of stuff for each digest type
    signoff = _('End of ') + digestid
    # MIME
    # BAW: This stuff is outside the normal MIME goo, and it's what the old
    # MIME digester did.  No one seemed to complain, probably because you
    # won't see it in an MUA that can't display the raw message.  We've never
    # got complaints before, but if we do, just wax this.  It's primarily
    # included for (marginally useful) backwards compatibility.
    mimemsg.postamble = signoff
    # rfc1153
    print(signoff, file=plainmsg)
    print('*' * len(signoff), file=plainmsg)
    # Do our final bit of housekeeping, and then send each message to the
    # outgoing queue for delivery.
    mlist.next_digest_number += 1
    virginq = get_switchboard(mm_cfg.VIRGINQUEUE_DIR)
    # Calculate the recipients lists
    plainrecips = []
    mimerecips = []
    drecips = mlist.getDigestMemberKeys() + list(mlist.one_last_digest.keys())
    for user in mlist.getMemberCPAddresses(drecips):
        # user might be None if someone who toggled off digest delivery
        # subsequently unsubscribed from the mailing list.  Also, filter out
        # folks who have disabled delivery.
        if user is None or mlist.getDeliveryStatus(user) != ENABLED:
            continue
        # Otherwise, decide whether they get MIME or RFC 1153 digests
        if mlist.getMemberOption(user, mm_cfg.DisableMime):
            plainrecips.append(user)
        else:
            mimerecips.append(user)
    # Zap this since we're now delivering the last digest to these folks.
    mlist.one_last_digest.clear()
    # MIME
    virginq.enqueue(mimemsg,
                    recips=mimerecips,
                    listname=mlist.internal_name(),
                    isdigest=True)
    # RFC 1153
    rfc1153msg.set_payload(to_cset_out(plainmsg.getvalue(), lcset), lcset)
    virginq.enqueue(rfc1153msg,
                    recips=plainrecips,
                    listname=mlist.internal_name(),
                    isdigest=True)
Example #22
0
def send_email(email_sender='me',
               email_to='',
               email_subject='',
               email_body_html='',
               email_cc='',
               email_bcc='',
               files=None):
    credentials = get_credentials()
    service = discovery.build(serviceName='gmail',
                              version='v1',
                              credentials=credentials)

    message = multipart.MIMEMultipart()
    message['to'] = email_to
    message['from'] = email_sender
    message['date'] = utils.formatdate(localtime=True)
    message['subject'] = email_subject
    message['cc'] = email_cc
    message['bcc'] = email_bcc
    message.attach(text.MIMEText(email_body_html, 'html'))

    for f in files or []:
        f = f.strip(' ')
        mimetype, encoding = mimetypes.guess_type(f)

        if mimetype is None or encoding is not None:
            mimetype = 'application/octet-stream'
        main_type, sub_type = mimetype.split('/', 1)

        if main_type == 'text':
            with open(f, 'rb') as outfile:
                attachement = text.MIMEText(outfile.read(), _subtype=sub_type)
        elif main_type == 'image':
            with open(f, 'rb') as outfile:
                attachement = image.MIMEImage(outfile.read(),
                                              _subtype=sub_type)
        elif main_type == 'audio':
            with open(f, 'rb') as outfile:
                attachement = audio.MIMEAudio(outfile.read(),
                                              _subtype=sub_type)
        elif main_type == 'application' and sub_type == 'pdf':
            with open(f, 'rb') as outfile:
                attachement = application.MIMEApplication(outfile.read(),
                                                          _subtype=sub_type)
        else:
            attachement = base.MIMEBase(main_type, sub_type)
            with open(f, 'rb') as outfile:
                attachement.set_payload(outfile.read())

        encoders.encode_base64(attachement)
        attachement.add_header('Content-Disposition',
                               'attachment',
                               filename=os.path.basename(f))
        message.attach(attachement)

    msg_bytes = message.as_bytes()
    print(f"Message size: {format_size(len(msg_bytes))}")
    media_body = http.MediaIoBaseUpload(io.BytesIO(msg_bytes),
                                        mimetype='message/rfc822',
                                        resumable=True)
    body_metadata = {}
    print('Sending...')
    try:
        response = service.users().messages().send(
            userId='me', body=body_metadata, media_body=media_body).execute()
        print(response)
    except errors.HttpError as error:
        print('Error:\n{}'.format(error))
Example #23
0
gmail_password = "******"
mail_to = "*****@*****.**"

subject = "Email from python"
body = "This email from python."
file_path = "./test.tar.gz"


encoding = "utf-8"
msg = multipart.MIMEMultipart()
msg["Subject"] = Header(subject, encoding)
msg["To"] = mail_to
msg["From"] = gmail_account
msg.attach(text.MIMEText(body, "plain", encoding))

attach = base.MIMEBase("application", "tar.gz")
with open(file_path, "br") as f:
    attach.set_payload(f.read())
encoders.encode_base64(attach)
attach.add_header(
    "Content-Disposition",
    "attachment",
    filename="attachment.tar.gz"
)
msg.attach(attach)


server = smtplib.SMTP_SSL("smtp.gmail.com", 465,
    context=ssl.create_default_context())
server.login(gmail_account, gmail_password)
server.send_message(msg)
    def _GenerateMIMEMessage(self, form, boundary=None):
        """Generate a new post from original form.

    Also responsible for storing blobs in the datastore.

    Args:
      form: Instance of cgi.FieldStorage representing the whole form
        derived from original post data.
      boundary: Boundary to use for resulting form.  Used only in tests so
        that the boundary is always consistent.

    Returns:
      A MIMEMultipart instance representing the new HTTP post which should be
      forwarded to the developers actual CGI handler. DO NOT use the return
      value of this method to generate a string unless you know what you're
      doing and properly handle folding whitespace (from rfc822) properly.
    """
        message = multipart.MIMEMultipart('form-data', boundary)
        for name, value in form.headers.items():
            if name.lower() not in STRIPPED_HEADERS:
                message.add_header(name, value)

        def IterateForm():
            """Flattens form in to single sequence of cgi.FieldStorage instances.

      The resulting cgi.FieldStorage objects are a little bit irregular in
      their structure.  A single name can have mulitple sub-items.  In this
      case, the root FieldStorage object has a list associated with that field
      name.  Otherwise, the root FieldStorage object just refers to a single
      nested instance.

      Lists of FieldStorage instances occur when a form has multiple values
      for the same name.

      Yields:
        cgi.FieldStorage irrespective of their nesting level.
      """
            for key in sorted(form):
                form_item = form[key]
                if isinstance(form_item, list):
                    for list_item in form_item:
                        yield list_item
                else:
                    yield form_item

        creation = self.__now_func()
        for form_item in IterateForm():

            disposition_parameters = {'name': form_item.name}

            if form_item.filename is None:
                variable = base.MIMEBase('text', 'plain')
                variable.set_payload(form_item.value)
            else:
                disposition_parameters['filename'] = form_item.filename

                main_type, sub_type = _SplitMIMEType(form_item.type)

                blob_entity = self.StoreBlob(form_item, creation)

                variable = base.MIMEBase('message',
                                         'external-body',
                                         access_type=blobstore.BLOB_KEY_HEADER,
                                         blob_key=blob_entity.key().name())

                form_item.file.seek(0, 2)
                content_length = form_item.file.tell()
                form_item.file.seek(0)

                external = base.MIMEBase(main_type, sub_type,
                                         **form_item.type_options)
                headers = dict(form_item.headers)
                headers['Content-Length'] = str(content_length)
                headers[
                    blobstore.UPLOAD_INFO_CREATION_HEADER] = _FormatDateTime(
                        creation)
                for key, value in headers.iteritems():
                    external.add_header(key, value)

                external_disposition_parameters = dict(disposition_parameters)
                external_disposition_parameters[
                    'filename'] = form_item.filename
                if not external.get('Content-Disposition'):
                    external.add_header('Content-Disposition', 'form-data',
                                        **external_disposition_parameters)
                variable.set_payload([external])

            variable.add_header('Content-Disposition', 'form-data',
                                **disposition_parameters)
            message.attach(variable)

        return message
def execute(sender, password, recipients, subject, body, attachments):
    print sender, password, recipients, subject, body, attachments

    backslash_map = {
        '\a': r'\a',
        '\b': r'\b',
        '\f': r'\f',
        '\n': r'\n',
        '\r': r'\r',
        '\t': r'\t',
        '\v': r'\v'
    }
    for key, value in backslash_map.items():
        recipients = recipients.replace(key, value)

    recipients = recipients.replace('\\', '\\\\')

    f = open(recipients, 'r')
    recipients = ' '.join(f.readlines())

    msg = multipart.MIMEMultipart()
    msg['From'] = sender
    msg['To'] = recipients
    msg['Subject'] = subject

    msg.attach(text.MIMEText(body, 'plain'))

    for filename in attachments:
        f = filename

        for key, value in backslash_map.items():
            f = f.replace(key, value)
        f = f.replace('\\', '\\\\')

        part = base.MIMEBase('application', "octet-stream")
        part.set_payload(open(f, "rb").read())
        encoders.encode_base64(part)
        part.add_header('Content-Disposition',
                        'attachment; filename="%s"' % os.path.basename(f))
        msg.attach(part)

    try:
        server = smtplib.SMTP('smtp.gmail.com', 587)
        server.set_debuglevel(False)

        server.starttls()
        server.login(sender, password)

    except socket.gaierror:
        print "Check your Internet Connection"
        return 2
    except smtplib.SMTPAuthenticationError:
        print "Invalid Username or Password"
        return 3
    except:
        print "Login Failed"
        return 4

    try:
        server.sendmail(msg['From'], recipients.split(), msg.as_string())
        print 'Email Sent Successfully'
        server.quit()
        return 1
    except:
        print "Email Not Sent"
        return 0