如何解决Python中hourmailer发送附件的JSON序列化错误?
问题
在项目中使用hourmailer发送带附件(如txt文件)的邮件时,执行response = requests.request("POST", url, json=payload, headers=headers)出现错误Object of type bytes is not JSON serializable,原因是attachment.read()读取的字节流无法被JSON序列化。原代码如下:
import requests url = "https://hourmailer.p.rapidapi.com/send" subject = str(input("Enter a subject:")) email_origin = str(input("Enter a Origin email:")) email_html_file = str(input("Enter the HTML file name:")) # open the file to be sent filename = "{email}".format(email=email_html_file) attachment = open("C:\PythonItems\Email\{email}".format(email=email_html_file), "rb") payload = { # "toAddress": "nellyordona@gmail.com", "fromAddress":email_origin, "toAddress": "jumo.vicentillo.sjc@phinmaed.com", "title": subject, "message": "Hi, I'm from {email}".format(email=email_origin), "attachment":attachment.read() } headers = { "content-type": "application/json", "X-RapidAPI-Key": "............", "X-RapidAPI-Host": "hourmailer.p.rapidapi.com" } response = requests.request("POST", url, json=payload, headers=headers) split = response.text.split(":")[1][:-1] if (split == '"Message sent to {text}"'.format(text="jumo.vicentillo.sjc@phinmaed.com")): print("Message sent to {text}".format(text="jumo.vicentillo.sjc@phinmaed.com!\n")) print("All messages sent!")
解决方法
JSON无法直接序列化字节流,核心解决思路是将附件内容转换为可被JSON序列化的格式,或改用适合传输文件的请求格式,以下两种方案可选:
方案一:将附件编码为Base64字符串(适配JSON请求)
把字节流转换为Base64编码的字符串,这是文本格式,可被JSON正常序列化。同时注意用with open自动管理文件句柄,避免资源泄漏:
import requests import base64 url = "https://hourmailer.p.rapidapi.com/send" subject = input("Enter a subject:") email_origin = input("Enter a Origin email:") email_html_file = input("Enter the HTML file name:") # 读取文件并编码为Base64字符串 file_path = f"C:\\PythonItems\\Email\\{email_html_file}" with open(file_path, "rb") as attachment: attachment_base64 = base64.b64encode(attachment.read()).decode('utf-8') payload = { "fromAddress": email_origin, "toAddress": "jumo.vicentillo.sjc@phinmaed.com", "title": subject, "message": f"Hi, I'm from {email_origin}", "attachment": attachment_base64, "attachmentName": email_html_file # 多数邮件API需指定附件文件名,需匹配hourmailer文档参数名 } headers = { "X-RapidAPI-Key": "............", "X-RapidAPI-Host": "hourmailer.p.rapidapi.com" } try: response = requests.post(url, json=payload, headers=headers) response.raise_for_status() # 主动抛出HTTP请求错误 if f'"Message sent to jumo.vicentillo.sjc@phinmaed.com"' in response.text: print("Message sent to jumo.vicentillo.sjc@phinmaed.com!\n") print("All messages sent!") else: print(f"发送失败,响应内容:{response.text}") except Exception as e: print(f"请求出错:{str(e)}")
方案二:改用multipart/form-data格式提交(更适合文件传输)
如果hourmailer API支持表单形式接收附件,直接用requests的files参数提交,无需编码转换:
import requests url = "https://hourmailer.p.rapidapi.com/send" subject = input("Enter a subject:") email_origin = input("Enter a Origin email:") email_html_file = input("Enter the HTML file name:") file_path = f"C:\\PythonItems\\Email\\{email_html_file}" payload = { "fromAddress": email_origin, "toAddress": "jumo.vicentillo.sjc@phinmaed.com", "title": subject, "message": f"Hi, I'm from {email_origin}" } files = { "attachment": open(file_path, "rb") } headers = { "X-RapidAPI-Key": "............", "X-RapidAPI-Host": "hourmailer.p.rapidapi.com" } try: response = requests.post(url, data=payload, files=files, headers=headers) response.raise_for_status() if f'"Message sent to jumo.vicentillo.sjc@phinmaed.com"' in response.text: print("Message sent to jumo.vicentillo.sjc@phinmaed.com!\n") print("All messages sent!") else: print(f"发送失败,响应内容:{response.text}") except Exception as e: print(f"请求出错:{str(e)}") finally: files["attachment"].close()
内容的提问来源于stack exchange,提问作者Myth Vince
相关产品推荐
相关产品推荐

