在C#中使用Gmail API发送带HTML模板的自动化邮件问题
在.NET C#中使用Gmail API发送带HTML模板的自动化邮件
我正在为公司开发一款.NET C#应用,尝试通过该应用使用HTML模板向用户发送自动化邮件时遇到了困难。
现有Gmail API发送邮件的C#代码
public bool sendEmail(SendEmailModel email) { try { UserCredential credential = loadCredentials(); string message = $"To: {email.receiver}\r\nSubject: {email.subject}\r\nContent-Type: text/html;charset=utf-8\r\n\r\n<h1>{email.content}</h1>"; var service = new GmailService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = ApplicationName }); var msg = new Google.Apis.Gmail.v1.Data.Message(); msg.Raw = Base64UrlEncode(message.ToString()); service.Users.Messages.Send(msg, "me").Execute(); return true; } catch(Exception ex) { return false; } } string Base64UrlEncode(string input) { var data = Encoding.UTF8.GetBytes(input); return Convert.ToBase64String(data).Replace("+", "-").Replace("/", "_").Replace("=", ""); }
准备使用的HTML模板
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="x-apple-disable-message-reformatting" content="true"> <title></title> <link href="https://fonts.googleapis.com/css?family=Poppins:200,300,400,500,600,700" rel="stylesheet"> <style> html, body { margin: 0 auto !important; padding: 0 !important; height: 100% !important; width: 100% !important; background: #f1f1f1; } * { -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; } div[style*="margin: 16px 0"] { margin: 0 !important; } table, td { mso-table-lspace: 0pt !important; mso-table-rspace: 0pt !important; } table { border-spacing: 0 !important; border-collapse: collapse !important; table-layout: fixed !important; margin: 0 auto !important; } img { -ms-interpolation-mode:bicubic; } a { text-decoration: none; } *[x-apple-data-detectors], /* iOS */ .unstyle-auto-detected-links *, .aBn { border-bottom: 0 !important; cursor: default !important; color: inherit !important; text-decoration: none !important; font-size: inherit !important; font-family: inherit !important; font-weight: inherit !important; line-height: inherit !important; } .a6S { display: none !important; opacity: 0.01 !important; } .im { color: inherit !important; } img.g-img + div { display: none !important; } @media only screen and (min-device-width: 320px) and (max-device-width: 374px) { u ~ div .email-container { min-width: 320px !important; } } @media only screen and (min-device-width: 375px) and (max-device-width: 413px) { u ~ div .email-container { min-width: 375px !important; } } @media only screen and (min-device-width: 414px) { u ~ div .email-container { min-width: 414px !important; } } </style> <style> .primary{ background: #17bebb; } .bg_white{ background: #ffffff; } .bg_light{ background: #f7fafa; } .bg_black{ background: #000000; } .bg_dark{ background: rgba(0,0,0,.8); } .email-section{ padding:2.5em; } .btn{ padding: 10px 15px; display: inline-block; } .btn.btn-primary{ border-radius: 25px; background: #e77d1a; color: #ffffff; } .btn.btn-white{ border-radius: 5px; background: #ffffff; color: #000000; } .btn.btn-white-outline{ border-radius: 25px; background: transparent; border: 1px solid #e77d1a; color: #e77d1a; } .btn.btn-black-outline{ border-radius: 0px; background: transparent; border: 2px solid #000; color: #000; font-weight: 700; } .btn-custom{ color: rgba(0,0,0,.3); text-decoration: underline; } h1,h2,h3,h4,h5,h6{ font-family: 'Poppins', sans-serif; color: #000000; margin-top: 0; font-weight: 400; } body{ font-family: 'Poppins', sans-serif; font-weight: 400; font-size: 15px; line-height: 1.8; color: rgba(0,0,0,.4); } a{ color: #17bebb; } .logo h1{ margin: 0; } .logo h1 a{ color: #17bebb; font-size: 24px; font-weight: 700; font-family: 'Poppins', sans-serif; } .hero{ position: relative; z-index: 0; } .hero .text{ color: rgba(0,0,0,.3); } .hero .text h2{ color: #000; font-size: 34px; margin-bottom: 0; font-weight: 200; line-height: 1.4; } .hero .text h3{ font-size: 24px; font-weight: 300; } .hero .text h2 span{ font-weight: 600; color: #000; } .text-author{ bordeR: 1px solid rgba(0,0,0,.05); max-width: 50%; margin: 0 auto; padding: 2em; } .text-author img{ border-radius: 50%; padding-bottom: 20px; } .text-author h3{ margin-bottom: 0; } ul.social{ padding: 0; } ul.social li{ display: inline-block; margin-right: 10px; } .footer{ border-top: 1px solid rgba(0,0,0,.05); color: rgba(0,0,0,.5); } .footer .heading{ color: #000; font-size: 20px; } .footer ul{ margin: 0; padding: 0; } .footer ul li{ list-style: none; margin-bottom: 10px; } .footer ul li a{ color: rgba(0,0,0,1); } @media screen and (max-width: 500px) { } </style> </head> <center style="width: 100%; background-color: #f1f1f1;"> <div style=" display: none; font-size: 1px;max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;"></div> <div style=" max-width: 900px; margin: 0 auto;" class="email-container"> <table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="background-color: #dedede; margin: auto;"> <tr> <td valign="middle" class="hero bg_white" style="background-color: #dedede; padding: 2em 0 2em 0;"> <div class="text-author" style="border-radius: 20px;background-color: #ffffff;border-color: #ffffff; "> <table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%"> <tr> <td style="text-align: center;"> <img src="{LOGO_1}" style="height: 100px; width: auto;"> </td> </tr> <tr> <td style="text-align: left;"> <h3 class="name" style="font-weight: 600; font-size: 25px; color: #171717;">Olá,</h3> <span class="position">{content}</span> </td> </tr> <tr > <td style="text-align: center;"> <p><a class="btn btn-white-outline" style="width: 94%;">{btn_1_content}</a></p> <p><a href="#" class="btn btn-primary" style="width: 94%;">{btn_2_content}</a></p> </td> </tr> <tr> <td style="text-align: left;"> <div style="height: 10px;"></div> <span class="position" style="color: #dbdbdb;">Este é um e-mail enviado automaticamente.</span> <div style="height: 10px;"></div> </td> </tr> <tr> <td style="text-align: left;"> <div class="separator" style="background-color: #d7d7d7; height: 1px;"></div> </td> </tr> <tr> <td style="text-align: center;"> <div style="height: 20px;"></div> <span class="position" style="color: #dbdbdb;">Se você já realizou o pagamento desse boleto desconsidere esse e-mail.</span> </td> </tr> <tr> <td style="text-align: left;"> <h3 class="name" style="font-weight: 250; font-size: 16px; color: #171717;">Abraços,</h3> <h3 class="name" style="font-weight: 600; font-size: 16px; color: #171717;">Equipe Acalanto.</h3> </td> </tr> </table> </div> </td> </tr> <tr> <td style="text-align: center;"> <div> <img src="{LOGO_2}" height="60px"> <h3 style="color: #898989; font-size: 14px;">© Organização Diamante LTDA</h3> </div> </td> </tr> </table> </div> </center> </body> </html>
我完全不清楚如何在Gmail API中使用这类模板。如果Gmail API不适用于这种场景,请告知我,我不介意使用其他邮件服务,不过我确实偏好谷歌相关产品,但目前找不到.NET C#相关的模板使用说明。
解决方案:用Gmail API发送带模板的HTML邮件
Gmail API完全支持发送HTML格式邮件,你只需要修改现有代码,将模板内容替换变量后作为邮件正文即可。以下是具体步骤:
1. 加载HTML模板文件
把HTML模板保存为.html文件(比如EmailTemplate.html),放在项目可访问的路径下,通过代码读取内容:
private string LoadEmailTemplate(string templatePath) { if (!File.Exists(templatePath)) throw new FileNotFoundException("邮件模板文件不存在"); return File.ReadAllText(templatePath, Encoding.UTF8); }
2. 替换模板中的变量
将模板里的{LOGO_1}、{content}等占位符替换为实际内容,基础替换方式如下:
private string ReplaceTemplateVariables(string template, SendEmailModel email, string logo1Url, string logo2Url, string btn1Text, string btn2Text) { return template .Replace("{LOGO_1}", logo1Url) .Replace("{LOGO_2}", logo2Url) .Replace("{content}", email.content) .Replace("{btn_1_content}", btn1Text) .Replace("{btn_2_content}", btn2Text); }
3. 修改sendEmail方法使用模板
更新原方法,替换硬编码的正文为处理后的模板内容:
public bool sendEmail(SendEmailModel email) { try { UserCredential credential = loadCredentials(); // 加载模板 string templatePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "EmailTemplate.html"); string htmlTemplate = LoadEmailTemplate(templatePath); // 替换变量(参数可根据实际需求调整) string htmlBody = ReplaceTemplateVariables( htmlTemplate, email, "你的LOGO1地址", "你的LOGO2地址", "按钮1文本", "按钮2文本" ); // 构造邮件内容 string message = $"To: {email.receiver}\r\nSubject: {email.subject}\r\nContent-Type: text/html;charset=utf-8\r\n\r\n{htmlBody}"; var service = new GmailService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = ApplicationName }); var msg = new Google.Apis.Gmail.v1.Data.Message(); msg.Raw = Base64UrlEncode(message); service.Users.Messages.Send(msg, "me").Execute(); return true; } catch(Exception ex) { // 建议添加异常日志记录 return false; } }
4. 注意事项
- 确保模板文件以UTF-8编码保存,读取时也用UTF-8,避免乱码。
- 原有的
Base64UrlEncode方法可正常使用,需确保整个邮件内容(头+正文)编码正确。 - 若模板复杂,可使用RazorEngine等模板引擎,支持循环、条件判断等复杂逻辑。
- 确认Gmail API凭据拥有
https://www.googleapis.com/auth/gmail.send权限。
谷歌系替代方案
如果觉得直接处理模板麻烦,可考虑Google Workspace Mail Merge(适合批量邮件场景),但Gmail API完全能满足需求,无需更换服务。
内容的提问来源于stack exchange,提问作者ReDevil
相关产品推荐
相关产品推荐

