Gmail 草稿(带附件的 HTML)与 MimeKit、C# Winforms 和 Google API
本文关键字:MimeKit Winforms API Google 草稿 HTML Gmail | 更新日期: 2023-09-27 18:36:27
我正在尝试使用 C# 在 winforms 应用程序中生成 Gmail 草稿邮件。草稿邮件需要采用 HTML 格式并能够包含附件。
我能够使用 AE.Net.Mail
生成带有附件的草稿,但草稿邮件是纯文本的(我不知道如何编码AE.Net.Mail
给我一个 HTML Gmail 草稿邮件)。
为了将消息转换为HTML格式,我使用MimeKit获取System.Net.Mail
消息并将其转换为MimeMessage
消息。但是,我无法弄清楚如何按照 Gmail 草稿规范的要求将 MIME 邮件放入 RFC 2822 格式且网址安全的 base64 编码字符串中。
以下是 MimeKit 转换尝试的代码:
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
MailMessage msg = new MailMessage(); //System.Net.Mail
msg.IsBodyHtml = true;
msg.Subject = "HTML Email";
msg.Body = "<a href = 'http://www.yahoo.com/'>Enjoy Yahoo!</a>";
msg.Attachments.Add(file);
MimeMessage message = MimeMessage.CreateFromMailMessage(msg); //MimeKit conversion
//At this point I cannot figure out how to get the MIME message into
//an RFC 2822 formatted and URL-safe base64 encoded string
//as required by the Gmail draft specification
//See working code below for how this works in AE.Net.Mail
以下是使用AE.Net.Mail
的代码,该代码有效,但将Gmail草稿的正文生成为纯文本(基于Jason Pettys的这篇文章):
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
var msg = new AE.Net.Mail.MailMessage //msg created in plain text not HTML format
{
Body = "<a href = 'http://www.yahoo.com/'>Enjoy Yahoo!</a>"
};
var bytes = System.IO.File.ReadAllBytes(filePath);
AE.Net.Mail.Attachment file = new AE.Net.Mail.Attachment(bytes, @"application/pdf", FileName, true);
msg.Attachments.Add(file);
var msgStr = new StringWriter();
msg.Save(msgStr);
Message m = new Message();
m.Raw = Base64UrlEncode(msgStr.ToString());
Draft draft = new Draft(); //Gmail draft
draft.Message = m;
service.Users.Drafts.Create(draft, "me").Execute();
private static string Base64UrlEncode(string input)
{
var inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
// Special "url-safe" base64 encode.
return Convert.ToBase64String(inputBytes)
.Replace('+', '-')
.Replace('/', '_')
.Replace("=", "");
}
有没有办法将 MimeKit 的MimeMessage
邮件转换为 RFC 2822 格式且网址安全的 base64 编码字符串,以便可以将其生成为 Gmail 草稿?如果做不到这一点,有没有办法在编码之前以 HTML 格式创建AE.Net.Mail
消息?非常感谢所有帮助。
做你想做的最简单的方法是这样的:
static string Base64UrlEncode (MimeMessage message)
{
using (var stream = new MemoryStream ()) {
message.WriteTo (stream);
return Convert.ToBase64String (stream.GetBuffer (), 0, (int) stream.Length)
.Replace ('+', '-')
.Replace ('/', '_')
.Replace ("=", "");
}
}
但更有效的方法需要实现我们自己的 UrlEncoderFilter 来替换您的".替换 (...)" 逻辑:
using MimeKit;
using MimeKit.IO;
using MimeKit.IO.Filters;
// ...
class UrlEncodeFilter : IMimeFilter
{
byte[] output = new byte[8192];
#region IMimeFilter implementation
public byte[] Filter (byte[] input, int startIndex, int length, out int outputIndex, out int outputLength)
{
if (output.Length < input.Length)
Array.Resize (ref output, input.Length);
int endIndex = startIndex + length;
outputLength = 0;
outputIndex = 0;
for (int index = startIndex; index < endIndex; index++) {
switch ((char) input[index]) {
case ''r': case ''n': case '=': break;
case '+': output[outputLength++] = (byte) '-'; break;
case '/': output[outputLength++] = (byte) '_'; break;
default: output[outputLength++] = input[index]; break;
}
}
return output;
}
public byte[] Flush (byte[] input, int startIndex, int length, out int outputIndex, out int outputLength)
{
return Filter (input, startIndex, length, out outputIndex, out outputLength);
}
public void Reset ()
{
}
#endregion
}
你使用它的方式是这样的:
static string Base64UrlEncode (MimeMessage message)
{
using (var stream = new MemoryStream ()) {
using (var filtered = new FilteredStream (stream)) {
filtered.Add (EncoderFilter.Create (ContentEncoding.Base64));
filtered.Add (new UrlEncodeFilter ());
message.WriteTo (filtered);
filtered.Flush ();
}
return Encoding.ASCII.GetString (stream.GetBuffer (), 0, (int) stream.Length);
}
}
这是我用来创建带有附件的 gmail 草稿的 C# 代码......
using System;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Gmail.v1;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System.IO;
using System.Threading;
using System.Net.Mail;
namespace SendStatusReportsAddin1
{
class Program
{
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/gmail-dotnet-quickstart.json
//static string[] Scopes = { GmailService.Scope.GmailReadonly };
static string[] Scopes = { GmailService.Scope.MailGoogleCom };
static string ApplicationName = "Gmail API .NET Quickstart";
static void Main(string[] args)
{
//Authorization
UserCredential credential;
using (var stream =
new FileStream("client_secret2.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials3/gmail-dotnet.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
//Create Gmail API service.
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
//Create mail message
MailMessage mailmsg = new MailMessage();
{
mailmsg.Subject = "My test subject";
mailmsg.Body = "<b>My smart message </b>";
mailmsg.From = new MailAddress("joe.blow@hotmail.com");
mailmsg.To.Add(new MailAddress("jeff.jones@gmail.com"));
mailmsg.IsBodyHtml = true;
}
//add attachment
string statusreportfile =
@"C:'Users'ey96a'Google Drive'10 Status-Vacation-Expense'Status Reports'UUM RewriteStatus Report.pdf";
Attachment data = new Attachment(statusreportfile);
mailmsg.Attachments.Add(data);
//Make mail message a Mime message
MimeKit.MimeMessage mimemessage = MimeKit.MimeMessage.CreateFromMailMessage(mailmsg);
//Use Base64URLEncode to encode the Mime message
Google.Apis.Gmail.v1.Data.Message finalmessage = new Google.Apis.Gmail.v1.Data.Message();
finalmessage.Raw = Base64UrlEncode(mimemessage.ToString());
//Create the draft email
var mydraft = new Google.Apis.Gmail.v1.Data.Draft();
mydraft.Message = finalmessage;
var resultdraft = service.Users.Drafts.Create(mydraft, "me").Execute();
//Send the email (instead of creating a draft)
var resultsend = service.Users.Messages.Send(finalmessage, "me").Execute();
//Open the SendStatusReports form
aOpenForm.myForm1();
} //end of Main
//Base64 URL encode
public static string Base64UrlEncode(string input)
{
var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
// Special "url-safe" base64 encode.
return System.Convert.ToBase64String(inputBytes)
.Replace('+', '-')
.Replace('/', '_')
.Replace("=", "");
}
} //end of class Program
}
如果做不到这一点,有没有办法创建一个AE。在编码之前采用HTML格式的Net.Mail消息?
你可以试试
msg.ContentType = "text/html";
在您的 AE 中。网络邮件邮件消息