使用C#创建Gmail API消息

13

我正在研究在我正在开发的应用程序中使用Gmail API。然而,我不确定如何将它们的Java或Python示例更改为C#。现有的样例具体如何更改?

在此处找到示例。


3
Java非常接近C#,你肯定尝试过将其转换,但不知何故失败了?也许将你尝试转换的内容发布出来,让人们帮助你找出错误是一个好的开始。 - Prescott
我正在寻找MimeMessageProperties等的相应对象,但快速搜索并没有帮助到我。 - muttley91
Google APIs都是REST APIs。文档会告诉你需要在REST API调用中传递哪些参数。 - Casey
3个回答

22

这是我使用MimeKit得到的工作结果。

public void SendEmail(MyInternalSystemEmailMessage email)
{
    var mailMessage = new System.Net.Mail.MailMessage();
    mailMessage.From = new System.Net.Mail.MailAddress(email.FromAddress);
    mailMessage.To.Add(email.ToRecipients);
    mailMessage.ReplyToList.Add(email.FromAddress);
    mailMessage.Subject = email.Subject;
    mailMessage.Body = email.Body;
    mailMessage.IsBodyHtml = email.IsHtml;

    foreach (System.Net.Mail.Attachment attachment in email.Attachments)
    {
        mailMessage.Attachments.Add(attachment);
    }

    var mimeMessage = MimeKit.MimeMessage.CreateFromMailMessage(mailMessage);

    var gmailMessage = new Google.Apis.Gmail.v1.Data.Message {
        Raw = Encode(mimeMessage)
    };

    Google.Apis.Gmail.v1.UsersResource.MessagesResource.SendRequest request = service.Users.Messages.Send(gmailMessage, ServiceEmail);

    request.Execute();
}

public static string Encode(MimeMessage mimeMessage)
{
    using (MemoryStream ms = new MemoryStream())
    {
        mimeMessage.WriteTo(ms);
        return Convert.ToBase64String(ms.GetBuffer())
            .TrimEnd('=')
            .Replace('+', '-')
            .Replace('/', '_');
    }
}

}

注意:如果您遇到电子邮件退信问题,很可能是由于未设置ReplyToList字段引起的。请参见:GMail API Emails Bouncing


2
我认为你不应该使用 mimeMessage.ToString()。根据 namespace MimeKit 中的备注:一般来说,不应该使用此方法返回的字符串将消息序列化到磁盘上。建议您改用 MimeKit.MimeMessage.WriteTo(System.IO.Stream,System.Threading.CancellationToken) - Doan Van Thang
@DoanVanThang 是的,这是可能的。也许在过去的五年中有所改变,或者这一直都应该是那样。感谢您的提示! - Xtros
2
我遇到了mimeMessage.ToString()的问题。字符ã ç ã á ..无法正确显示。我在以下链接中找到了解决方案: https://stackoverflow.com/questions/55402719/sending-email-with-gmail-api-encoding-greek-characters-in-body - ChrCury78
我可以确认,截至07/2021,使用最新版本的MimeKit和Gmail API SDK,mimeMessage.ToString()方法根本行不通(API返回“需要收件人地址”错误)。由@ChrCury78发布的链接(https://stackoverflow.com/questions/55402719/sending-email-with-gmail-api-encoding-greek-characters-in-body)提供了可行的解决方案(将`MimeMessage`写入流而不是使用`ToString()`)。应该使用提供的代码更新此答案。我花了几个小时才弄清楚。 - thankyoussd
@thankyoussd 因为我没有编写过那段代码,也没有验证过它,也不会去验证。链接的问题回答了你遇到的具体问题。不幸的是,答案不能成为一个随着每个库更新而维护的活文档。这个答案在5年前发布时有效。 - Xtros
显示剩余2条评论

7

这是一个棘手的问题,但我最终解决了它。我使用了NuGet包AE.Net.Mail来获取RFC 2822位。

using System.IO;
using System.Net.Mail;
using Google.Apis.Gmail.v1;
using Google.Apis.Gmail.v1.Data;

public class TestEmail {

  public void SendIt() {
    var msg = new AE.Net.Mail.MailMessage {
      Subject = "Your Subject",
      Body = "Hello, World, from Gmail API!",
      From = new MailAddress("[you]@gmail.com")
    };
    msg.To.Add(new MailAddress("yourbuddy@gmail.com"));
    msg.ReplyTo.Add(msg.From); // Bounces without this!!
    var msgStr = new StringWriter();
    msg.Save(msgStr);

    var gmail = new GmailService(MyOwnGoogleOAuthInitializer);
    var result = gmail.Users.Messages.Send(new Message {
      Raw = Base64UrlEncode(msgStr.ToString())
    }, "me").Execute();
    Console.WriteLine("Message ID {0} sent.", result.Id);
  }

  private static string Base64UrlEncode(string input) {
    var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
    // Special "url-safe" base64 encode.
    return Convert.ToBase64String(inputBytes)
      .Replace('+', '-')
      .Replace('/', '_')
      .Replace("=", "");
  }
}

这里发布了一些进一步分析和原因相同的代码: http://jason.pettys.name/2014/10/27/sending-email-with-the-gmail-api-in-net-c/


我尝试使用你的代码,但是我遇到了错误 error CS0103: The name 'Context' does not exist in the current context on Context.GoogleOAuthInitializer。你从哪里得到了 Context? - Rossini
@Rossini 对于那里的混淆我很抱歉——那是指我的代码,它返回一个Google.Apis.Services.BaseClientService.Initializer,该初始化程序设置为在每个请求中添加OAuth2 Bearer令牌。你可能可以只使用默认的GmailService()构造函数——这取决于你的GmailService如何进行身份验证。我会更新我的代码,尽量让它更清晰明了。 - pettys
1
这段代码可以正常处理纯文本邮件,但无法处理带有HTML和附件的邮件。 - Allen King
1
对于未来查看此内容的任何人,请确保使用 AE.Net.Mail Nuget 包(https://www.nuget.org/packages/AE.Net.Mail/)而不是 System.Net.Mail(https://msdn.microsoft.com/en-us/library/system.net.mail(v=vs.110).aspx)。它们非常相似,但工作方式略有不同(例如,`System.Net.Mail.MailMessage` 没有 Save 方法)。 - derekantrican

-1

看起来这并不是Gmail API的问题。你应该寻找的是"c#创建电子邮件"(可能需要添加"RFC 2822",因为这是定义这些电子邮件格式的RFC)。一旦你拥有了这样一个有效的"电子邮件消息"(真正的、完整的电子邮件内容,可以与SMTP或IMAP等一起使用),那么将其与Gmail API一起使用就应该非常简单。


1
你说得对。我之前在 Gmail API 下发布了帖子,想着可能有人遇到过这个问题并且有答案,但是我应该更多地将它指向 C#。谢谢。 - muttley91
@rar 你找到什么了吗?我也在尝试解决同样的问题。 - pettys
1
很遗憾,我们不得不放弃Gmail API,因为它并没有发挥作用,而且我们没有太多时间去花费在上面,当我们可以使用更简单的电子邮件发送器时。谷歌真的应该改进他们的文档... - muttley91
1
@rar 感谢您的回复。我最终使用NuGet包AE.Net.Mail(https://github.com/andyedinborough/aenetmail)成功获取了原始的RFC 2822消息字节。我知道您所说的Gmail API是什么意思——我花了一整天才终于让它发送了一条消息。 - pettys
rar/pettys:你到底遇到了什么问题,或者文档应该如何改进?在我看来,最难的部分似乎是创建电子邮件消息,这与使用SMTP、API或IMAP无关。一旦你有了电子邮件消息字符串,只需对其进行base64url编码并将其POST到正确的URL上就很容易了,而且有很好的Java代码可以展示。 - Eric D

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接