Python:连续发送多个电子邮件时出错

我的发展使我能够发送电子邮件。如果我尝试向一张收据发送电子邮件,那没有问题。但是,如果我尝试将同一封电子邮件发送给多个收据,那么我会出错。我不想向多张收据发送电子邮件,我要向每张收据发送一封电子邮件。

我遇到的错误是:

  File "/home/josecarlos/Workspace/python/reports/reports/pregame.py",line 22,in __init__
    self.send_mail(subject,message,fileName)
  File "/home/josecarlos/Workspace/python/reports/reports/report.py",line 48,in send_mail
    message = mail.create_message()
  File "/home/josecarlos/Workspace/python/reports/com/mail/mail.py",line 100,in create_message
    message.attach(MIMEText(self.params["message"],"plain"))
  File "/usr/lib/python3.6/email/mime/text.py",line 34,in __init__
    _text.encode('us-ascii')
AttributeError: 'dict' object has no attribute 'encode'

要发送电子邮件,我需要上此类:

import base64
import logging
import os
import os.path
import pickle
from email import encoders
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient import errors
from googleapiclient.discovery import build


class Mail:
    def __init__(self,params):
        '''
        :param params: It's a dictionary with these keys:
        from: Email account from the email is sended
        to: Email account who will receive the email
        subject: Subject of the email
        message: Message of the email.
        game: Next games
        '''
        self.params = params

    @staticmethod
    def get_service():
        """Gets an authorized Gmail API service instance.

        Returns:
            An authorized Gmail API service instance..
        """

        # If modifying these scopes,delete the file token.pickle.
        SCOPES = [
            #'https://www.googleapis.com/auth/gmail.readonly','https://www.googleapis.com/auth/gmail.send',]
        creds = None
        # The file token.pickle stores the user's access and refresh tokens,and is
        # created automatically when the authorization flow completes for the first
        # time.
        if os.path.exists('token.pickle'):
            with open('token.pickle','rb') as token:
                creds = pickle.load(token)
        # If there are no (valid) credentials available,let the user log in.
        if not creds or not creds.valid:
            if creds and creds.expired and creds.refresh_token:
                creds.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file(
                    'com/mail/credentials.json',SCOPES)
                creds = flow.run_local_server(port=0)
            # Save the credentials for the next run
            with open('token.pickle','wb') as token:
                pickle.dump(creds,token)
        service = build('gmail','v1',credentials=creds)
        return service

    @staticmethod
    def send_message(service,sender,message):
      """Send an email message.

      Args:
        service: Authorized Gmail API service instance.
        sender: User's email address. The special value "me"
        can be used to indicate the authenticated user.
        message: Message to be sent.

      Returns:
        Sent Message.
      """
      try:
        sent_message = (service.users().messages().send(userId=sender,body=message)
                   .execute())
        logging.info('Message Id: %s',sent_message['id'])
        return sent_message
      except errors.HttpError as error:
        logging.error('An HTTP error occurred: %s',error)

    def create_message(self):
        """Create a message for an email.

        Args:
        sender: Email address of the sender.
        to: Email address of the receiver.
        subject: The subject of the email message.
        message_text: The text of the email message.

        Returns:
        An object containing a base64url encoded email object.
        """
        #message = MIMEText(message_text)
        message = MIMEMultipart()
        message['from'] = self.params["from"]
        message['to'] = self.params["to"]
        message['subject'] = self.params["subject"]
        message.attach(MIMEText(self.params["message"],"plain"))
        routeFile = self.params["routeFile"] + self.params["fileName"]
        fileName = self.params["fileName"]
        # Open PDF file in binary mode
        with open(routeFile,"rb") as attachment:
            # Add file as application/octet-stream
            # Email client can usually download this automatically as attachment
            part = MIMEBase("application","octet-stream")
            part.set_payload(attachment.read())

        # Encode file in ASCII characters to send by email
        encoders.encode_base64(part)
        # Add header as key/value pair to attachment part
        part.add_header(
            "Content-Disposition",f"attachment; filename= {fileName}",)
        # Add attachment to message and convert message to string
        message.attach(part)
        s = message.as_string()
        b = base64.urlsafe_b64encode(s.encode('utf-8'))
        return {'raw': b.decode('utf-8')}

要发送电子邮件,我将使用以下方法:

def send_mail(self,subject,fileName):
    args = self.params["destiny"]
    if self.params["competition"] == COMPETITIONS.LF1 or self.params["competition"] == COMPETITIONS.LF2:
         data = SearchData(args,"subscriptors.emails=")
    else:
         data = SearchDataFIBA(args,"subscriptors.emails=")
    emails = data.get_result().getData()

    for item in emails:
         print(f"Enviamos informe a la cuenta: {item['email']}")
         params = {
             "from" : "basketmetrics@gmail.com","to" : item["email"],"subject": subject,"message" : message,"fileName" : fileName,"routeFile" : f"output/reports/{self.params['destiny']}/"
        }
        mail = Mail(params)
        message = mail.create_message()
        service = mail.get_service()
        mail.send_message(service,"basketmetrics@gmail.com",message)

我的应用程序可以安全访问Google帐户。

我不知道如何在没有电子邮件的情况下连续发送超过一封电子邮件

仅发送一封电子邮件的问题。

我做错什么了吗?

编辑我:

要重现该错误,可以使用以下测试代码对其进行测试:

import unittest
import os
from com.mail.mail import Mail


class TestSendMail(unittest.TestCase):
    def setUp(self) -> None:
        os.chdir(os.path.abspath(os.path.join(os.path.dirname( __file__ ),'..')))
def test_send_mail(self):
    message = "¡¡¡Hola!!!\n\nOs enviamos el informe pre partido previo a vuestro próximo partido.\n\nSaludos,\n\nBasketmetrics.com"
    subject = "Informe pre partido"
    fileName = "name_of_the_file"
    emails = [{"email" : "receipt1@gmail.com"},{"email" : "receipt2@gmail.com"}]

    for item in emails:
        print(f"Enviamos informe a la cuenta: {item['email']}")
        params = {
            "from" : "sender@gmail.com","routeFile" : "route to the file"
        }
        mail = Mail(params)
        message = mail.create_message()
        service = mail.get_service()
        mail.send_message(service,"sender@gmail.com",message)

此外,您还必须为自己的值和您自己的Google帐户的文件certificate.json文件更改一些值

编辑II:

我发现它在哪里产生错误,但为什么呢?当我第二次调用班级邮件时出现问题。在那一刻,我将一些参数传递给带有params变量的构造函数。在该变量中,我传递消息的文本。此消息是在循环外部创建的。

如果我在构造函数的params [“ message”]中读取了接收Mail类的邮件的前120个字符:

def __init__(self,params):
    '''
    :param params: It's a dictionary with these keys:
    from: Email account from the email is sended
    to: Email account who will receive the email
    subject: Subject of the email
    message: Message of the email.
    game: Next games
    '''
    self.params = params
    print(f"message received: {params['message'][:120]}")

我第一次有了message变量的内容:

message received: ¡¡¡Hola!!!

Os enviamos el informe pre partido previo a vuestro próximo partido.

Saludos,Basketmetrics.com

但是第二次,我应该收到相同的文本!!!但我收到一个错误:

Error
Traceback (most recent call last):
  File "/usr/lib/python3.6/unittest/case.py",line 59,in testPartExecutor
    yield
  File "/usr/lib/python3.6/unittest/case.py",line 605,in run
    testMethod()
  File "/home/josecarlos/Workspace/python/reports/test/test_send_mail.py",line 26,in test_send_mail
    mail = Mail(params)
  File "/home/josecarlos/Workspace/python/reports/com/mail/mail.py",line 27,in __init__
    print(f"message received: {params['message'][:120]}")
TypeError: unhashable type: 'slice'

如果我阅读所有消息,没有任何限制或字符。我第一次收到可变消息的内容。但是第二次,我收到了一个很大的字符串os字符,这是一个小例子:

lGWFBVZzhQc3pDNWdiNmhnMW1odDZHcmlFZWsyClZvTTBRT1R2dXpWaWlyZkpleS9mZXhtR3V3V2hTV0JjWERtSUNnWENTQVJ1QjdrN1Nzd3BrZ0c1Rkl3MXVDMmNyZk95ZUhySVM1dHQKSUh2T1YvWW1Pd2YzL3B2WEpLaEMza

为什么我收到此字符串而不是message变量的值?

我已经检查过,如果我将消息变量放在for循环内,而不是在循环外...有效!我收到两封邮件!!!

但是,此解决方案没有用,因为我想重用我的代码,并且需要通过变量传递一些值。

那么,为什么第二次我没有收到message变量的值,却收到一长串字符?

如何解决此错误?为什么会发生此错误?

编辑III:

第一次检查我在Mail的构造函数中收到的值的类型是“字符串”:

typeof: <class 'str'>

但是第二次是“ dict”:

typeof: <class 'dict'>

检查self.params [“ message”]的键是:

keys: dict_keys(['raw'])

我一无所知... params [“ message”]可能具有message变量的值,而第二次params [“ message”]却已将其类型修改为raw吗?

编辑IV:

我从...修改了消息变量的内容。

message =“”

致...

message =“” Hola !!! 0x0a0x0aOs enviamos el informatione part part previo previo a vuestropróximopartido.0x0a0x0aSaludos,0x0a0x0aBasketmetrics.com“

但是它不起作用。我有同样的错误。

修改V:

我修改了消息变量的内容。现在,我要发送的不是HTML,而是纯文本。

    message = """\
    <html>
        <head></head>
        <body>
            <p>
                Hi,this is a test!!!
            </p>
            <p>
                Best regards!!!
            </p>
        </body>
    </html>
    """

要发送此消息,您必须在Mail类的create_message方法中修改此指令:

message.attach(MIMEText(self.params [“ message”],“普通”))

对此:

message.attach(MIMEText(self.params [“ message”],“ html”))

然后...我也有同样的错误!

我不知道该怎么办...

编辑VI:

最后一次尝试...我修改了消息的文本,删除了诸如“”或“

所以,我的消息变量现在是:

message = "Hello"

我再次修改了电子邮件的格式,从“ html”更改为“普通”

然后...我的第二封电子邮件中有相同的错误!!

这真令人沮丧...:(((((((

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Python中的函数(二) 在上一篇文章中提到了Python中函数的定义和使用,在这篇文章里我们来讨论下关于函数的一些更深的话题。在学习C语言函数的时候,遇到的问题主要有形参实参的区别、参数的传递和改变、变量的作用域。同样在Python中,关于对函数的理解和使用也存在这些问题。下面来逐一讲解。一.函
Python中的字符串 可能大多数人在学习C语言的时候,最先接触的数据类型就是字符串,因为大多教程都是以&quot;Hello world&quot;这个程序作为入门程序,这个程序中要打印的&quot;Hello world&quot;就是字符串。如果你做过自然语言处理方面的研究,并且用Python
Python 面向对象编程(一) 虽然Python是解释性语言,但是它是面向对象的,能够进行对象编程。下面就来了解一下如何在Python中进行对象编程。一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法。 类是对现实世界中一些事物的封装,
Python面向对象编程(二) 在前面一篇文章中谈到了类的基本定义和使用方法,这只体现了面向对象编程的三大特点之一:封装。下面就来了解一下另外两大特征:继承和多态。 在Python中,如果需要的话,可以让一个类去继承一个类,被继承的类称为父类或者超类、也可以称作基类,继承的类称为子类。并且Pytho
Python中的函数(一) 接触过C语言的朋友对函数这个词肯定非常熟悉,无论在哪门编程语言当中,函数(当然在某些语言里称作方法,意义是相同的)都扮演着至关重要的角色。今天就来了解一下Python中的函数用法。一.函数的定义 在某些编程语言当中,函数声明和函数定义是区分开的(在这些编程语言当中函数声明
在windows下如何快速搭建web.py开发框架 用Python进行web开发的话有很多框架供选择,比如最出名的Django,tornado等,除了这些框架之外,有一个轻量级的框架使用起来也是非常方便和顺手,就是web.py。它由一名黑客所创建,但是不幸的是这位创建者于2013年自杀了。据说现在由
将Sublime Text 2搭建成一个好用的IDE 说起编辑器,可能大部分人要推荐的是Vim和Emacs,本人用过Vim,功能确实强大,但是不是很习惯,之前一直有朋友推荐SUblime Text 2这款编辑器,然后这段时间就试了一下,就深深地喜欢上这款编辑器了...
Python中的模块 有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt这个函数,必须用语句&quot;#include&lt;math.h&gt;&quot;引入math.h这个头文件,否则是无法正常进行调用的。那么在Python中,如果要引用一些内置的函数,该怎么处理呢?在Python中
Python的基础语法 在对Python有了基础的认识之后,下面来了解一下Python的基础语法,看看它和C语言、java之间的基础语法差异。一.变量、表达式和语句 Python中的语句也称作命令,比如print &quot;hello python&quot;这就是一条语句。 表达式,顾名思义,是
Eclipse+PyDevʽjango+Mysql搭建Python web开发环境 Python的web框架有很多,目前主流的有Django、Tornado、Web.py等,最流行的要属Django了,也是被大家最看好的框架之一。下面就来讲讲如何搭建Django的开发环境。一.准备工作 需要下载的
在windows下安装配置Ulipad 今天推荐一款轻便的文本编辑器Ulipad,用来写一些小的Python脚本非常方便。 Ulipad下载地址: https://github.com/limodou/ulipad http://files.cnblogs.com/dolphin0520/u...
Python中的函数(三) 在前面两篇文章中已经探讨了函数的一些相关用法,下面一起来了解一下函数参数类型的问题。在C语言中,调用函数时必须依照函数定义时的参数个数以及类型来传递参数,否则将会发生错误,这个是严格进行规定的。然而在Python中函数参数定义和传递的方式相比而言就灵活多了。一.函数参数的
在Notepad++中搭配Python开发环境 Python在最近几年一度成为最流行的语言之一,不仅仅是因为它简洁明了,更在于它的功能之强大。它不仅能够完成一般脚本语言所能做的事情,还能很方便快捷地进行大规模的项目开发。在学习Python之前我们来看一下Python的历史由来,&quot;Pytho
Python中的条件选择和循环语句 同C语言、Java一样,Python中也存在条件选择和循环语句,其风格和C语言、java的很类似,但是在写法和用法上还是有一些区别。今天就让我们一起来了解一下。一.条件选择语句 Python中条件选择语句的关键字为:if 、elif 、else这三个。其基本形式如
关于raw_input( )和sys.stdin.readline( )的区别 之前一直认为用raw_input( )和sys.stdin.readline( )来获取输入的效果完全相同,但是最近在写程序时有类似这样一段代码:import sysline = sys.stdin.readline()
初识Python 跟学习所有的编程语言一样,首先得了解这门语言的编程风格和最基础的语法。下面就让我们一起来了解一下Python的编程风格。1.逻辑行与物理行 在Python中有逻辑行和物理行这个概念,物理行是指在编辑器中实际看到的一行,逻辑行是指一条Python语句。在Python中提倡一个物理行只
当我们的代码是有访问网络相关的操作时,比如http请求或者访问远程数据库,经常可能会发生一些错误,有些错误可能重新去发送请求就会成功,本文分析常见可能需要重试的场景,并最后给出python代码实现。
1.经典迭代器 2.将Sentence中的__iter__改成生成器函数 改成生成器后用法不变,但更加简洁。 3.惰性实现 当列表比较大,占内存较大时,我们可以采用惰性实现,每次只读取一个元素到内存。 或者使用更简洁的生成器表达式 4.yield from itertools模块含有大量生成器函数可
本文介绍简单介绍socket的常用函数,并以python-kafka中的源码socketpair为例,来讲解python socket的运用
python实践中经常出现编码相关的异常,大多网上找资料而没有理解原理,导致一次次重复错误。本文对常用Unicode、UTF-8、GB2312编码的原理进行介绍,接着介绍了python字符类型unicode和str以及常见编解码错误UnicodeEncodeError和UnicodeDEcodeEr