[Csharp]寄送Gmail使用OAuth2

這是一個desktop application桌面應用程式,主要功能利用Gmail寄送郵件。

首先查看Google文件說明,並使用其範例做修改。

1.開啟Gmail API功能

  1. 使用這個連結Google Developers Console建立一個專案並啟用API, 按繼續,來到憑證頁面
  2. 在增加憑證到您的專案頁面,按取消按鈕。
  3. 在頁面頂部,選擇OAuth同意畫面tab。 選擇一個電子郵件地址,輸入一個產品名稱(如果尚未設置),然後單擊儲存按鈕。
  4. 選擇憑證tab,按下建立憑證按鈕,選擇OAuth用戶端ID
  5. 選擇其它,並輸入一個名稱識別,按下建立按鈕。
  6. 建立完成會顯示您的用戶端ID及用戶端密鑰等資訊,按下確定按鈕。
  7. 按下”下載JSON“圖示,把檔案拉至專案Properties目錄,並設定複制到輸出目錄:一律複製

2.建立一個專案,並利用NuGet封裝管理員(工具->NuGet封裝管理員)來增加參考Google.Apis.Gmail.v1。

3.把文件裡的Example copy到Program.cs取代

using Google.Apis.Auth.OAuth2;
using Google.Apis.Gmail.v1;
using Google.Apis.Gmail.v1.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace GmailQuickstart
{
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 ApplicationName = "Gmail API .NET Quickstart";
static void Main(string[] args)
{
UserCredential credential;
using (var stream =
new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/gmail-dotnet-quickstart.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,
});
// Define parameters of request.
UsersResource.LabelsResource.ListRequest request = service.Users.Labels.List("me");
// List labels.
IList<Label> labels= request.Execute().Labels;
Console.WriteLine("Labels:");
if (labels != null && labels.Count > 0)
{
foreach (var labelItem in labels)
{
Console.WriteLine("{0}", labelItem.Name);
}
}
else
{
Console.WriteLine("No labels found.");
}
Console.Read();
}
}
}

4.執行看看,可以取得所有Label項目。

修改後的後可以寄信及附檔的原始檔如下:

using Google.Apis.Auth.OAuth2;
using Google.Apis.Gmail.v1;
using Google.Apis.Gmail.v1.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using log4net;
using System;
using System.IO;
using System.Net.Mail;
using System.Net.Mime;
using System.Threading;
using System.Web;
namespace GMailSender
{
class Program
{
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/gmail-dotnet-quickstart.json
static string[] Scopes = { GmailService.Scope.GmailSend };//GmailService.Scope.GmailReadonly
static string ApplicationName = "Gmail Sender";
private static readonly ILog logger = LogManager.GetLogger(typeof(Program));
static void Main(string[] args)
{
logger.Debug("args.length:" + args.Length);
if (args.Length != 2 && args.Length < 5)
{
Console.WriteLine("參數(均為必輸):\r\n GMailSender.exe 寄件者 標題 內文 收件者 附件");
return;
}
if (args[1] == "init" || args.Length >= 5)
{
UserCredential credential;
using (var stream =
new FileStream("Properties/client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/example-gmail.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
logger.Debug("Credential file saved to: " + credPath);
// Console.WriteLine("Credential file saved to: " + credPath);
}
// Create Gmail API service.
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
logger.Info("GMailSender.exe " +args[0] +";"+ args[1] + ";" + args[2] + ";" + args[3] + ";" + args[4] );
if (args.Length >= 5)
{
try
{
var msg = new AE.Net.Mail.MailMessage
{
Subject = "=?utf8?B?"+Program.Base64UrlEncode(args[1])+ "?=",
Body = args[2],
From = new MailAddress(args[0])
};
//msg.ReplyTo = new MailAddress(args[0]);
// msg.Encoding = System.Text.Encoding.GetEncoding("Utf8");
// msg.Encoding = Base64UrlEncode.
String attachmentFilename = args[4];
if (!File.Exists(attachmentFilename))
{
logger.Info("附加檔案不存在:" + attachmentFilename);
Console.WriteLine("附加檔案不存在:" + attachmentFilename);
return;
}
if (attachmentFilename != null && attachmentFilename != String.Empty)
{
AE.Net.Mail.Attachment attachment = new AE.Net.Mail.Attachment(File.ReadAllBytes(attachmentFilename), DispositionTypeNames.Attachment, Path.GetFileName(attachmentFilename), true);
msg.Attachments.Add(attachment);
}
msg.To.Add(new MailAddress(args[3]));
msg.ReplyTo.Add(msg.From); // Bounces without this!!
var msgStr = new StringWriter();
msg.Save(msgStr);
var newMsg = new Google.Apis.Gmail.v1.Data.Message();
newMsg.Raw = Program.Base64UrlEncode(msgStr.ToString());
service.Users.Messages.Send(newMsg, "me").Execute();
}
catch (Exception e)
{
logger.Info("寄送時發生錯誤:", e);
Console.Write(e.Message);
return;
}
logger.Info("寄件成功!");
}
}
// Console.Read();
}
public static string Base64UrlEncode(string input)
{
var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
return Convert.ToBase64String(inputBytes).Replace("+", "-").Replace("/", "_").Replace("=", "");
}
}
}

參考資料:

One thought to “[Csharp]寄送Gmail使用OAuth2”

  1. 謝謝你的分享,有一點要建議的事,subject部分不要使用Base64UrlEncode,因為它是考量safe url code,因此移除了一些字元,你可以用”使用者心得”這幾個字寄信測試看看,會發現收到的信件主旨是亂碼,subject轉碼部分用底下function即可
    public static string Base64UrlEncode(string input)
    {
    var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
    return Convert.ToBase64String(inputBytes);
    }

發表迴響