Ruby脚本调用Gmail API插入邮件异常:空邮件无发件人主题
解决Gmail API插入邮件无发件人、无主题的问题
问题根源
代码核心问题出在Base64编码处理和Mail gem生成的邮件格式兼容性上:
Base64.urlsafe_encode64默认会每60个字符插入换行符,而Gmail API要求raw字段是无换行的连续Base64URL编码字符串,换行会导致Gmail无法正确解析邮件头。- Mail gem生成的邮件头未显式指定UTF-8编码,可能导致Gmail解析时丢失主题、发件人等关键信息。
修复方案
1. 修正Base64编码逻辑
移除编码后的换行符,确保raw字段为连续字符串:
raw = Base64.urlsafe_encode64(message.to_s).gsub("\n", "")
2. 显式设置邮件字符编码
在Mail构建块中添加UTF-8编码声明,确保邮件头和正文的编码兼容性:
message = Mail.new do from sender to to subject subject charset 'UTF-8' # 全局字符集声明 text_part do body plain_text charset 'UTF-8' # 纯文本部分编码 end html_part do content_type 'text/html; charset=UTF-8' body html_content charset 'UTF-8' # HTML部分编码 end end
3. 确认Service Account配置
虽然Python版本正常运行,仍需验证:
- Service Account已启用域范围委派
- Google Admin控制台中已为该账号授权
https://www.googleapis.com/auth/gmail.insert权限 - 被模拟的用户邮箱属于你的G Suite/Workspace域
修改后的完整代码
require 'google/apis/gmail_v1' require 'googleauth' require 'base64' require 'mail' class GmailServiceAccount SCOPES = ['https://www.googleapis.com/auth/gmail.insert'] def initialize(service_account_file) @service_account_file = service_account_file @token_cache = {} end def get_service(user_email) return @token_cache[user_email] if @token_cache.key?(user_email) credentials = Google::Auth::ServiceAccountCredentials.make_creds( json_key_io: File.open(@service_account_file), scope: SCOPES ).dup credentials.sub = user_email service = Google::Apis::GmailV1::GmailService.new service.authorization = credentials @token_cache[user_email] = service service end def create_html_message(sender, to, subject, html_content, plain_text = nil) plain_text ||= "Please use an HTML capable email client to view this message." message = Mail.new do from sender to to subject subject charset 'UTF-8' text_part do body plain_text charset 'UTF-8' end html_part do content_type 'text/html; charset=UTF-8' body html_content charset 'UTF-8' end end puts "Constructed Message:\n#{message}" raw = Base64.urlsafe_encode64(message.to_s).gsub("\n", "") { raw: raw } end def insert_html_email(user_email, sender, subject, html_template_path, template_variables = {}) begin html_content = File.read(html_template_path, encoding: 'utf-8') template_variables.each do |key, value| html_content.gsub!("{{ #{key} }}", value.to_s) end service = get_service(user_email) message = create_html_message(sender, user_email, subject, html_content) puts "Encoded Raw Message:\n#{message[:raw]}" message_body = { raw: message[:raw], labelIds: ['INBOX', 'UNREAD'] } result = service.insert_user_message(user_email, message_body) { user: user_email, status: 'success', message_id: result.id } rescue => e { user: user_email, status: 'error', error: e.message } end end end # Command-line execution if __FILE__ == $0 service_account_file = 'path/to/your/service-account-key.json' user_email = 'recipient@example.com' sender = 'sender@example.com' subject = 'Test Email' html_template_path = 'email_template.html' template_variables = { 'name' => 'John Doe' } gmail_service = GmailServiceAccount.new(service_account_file) result = gmail_service.insert_html_email(user_email, sender, subject, html_template_path, template_variables) puts result end
验证步骤
- 运行代码后,检查Debug输出的
Constructed Message是否包含完整的From、To、Subject头和正文内容。 - 确认
Encoded Raw Message是无换行的连续字符串。 - 查看收件箱,验证邮件是否正常显示发件人、主题和内容。
内容的提问来源于stack exchange,提问作者Nacio-Félix Laubressac
相关产品推荐
相关产品推荐

