今回は Xamarin でメーラーを利用してメールを送信する方法についてご紹介いたします。バックグラウンドで直接送信する場合は MailKit 等でも送信ができますが、この記事ではフロントエンドでユーザーが内容を修正できるように他のメーラーアプリを画面表示して送信する方法を試してみました。
iOS と Android で同じ呼び出しコードにするため、毎度お馴染みDependencyService での記述になりますが、Android では少し気を付ける点があります。
Android5

Android4

前提条件
・Windows10
・Visual Studio 2015 Community Update3
・Xamarin 4.3.0.784 (NuGet Xamarin.Forms 2.3.4.224)
・macOS Sierra 10.12.4 / Xcode8.3.1 / Xamarin.iOS 10.4.0.123
1.PCLの記述方法
PCLプロジェクト内に DependencyService で呼び出すためのインターフェースを配置します。
IMailService.cs
namespace AppName.Services
{
public interface IMailService
{
bool StartMailer(string title, string body, string[] to, string[] cc, string[] bcc, string filePath, ref string err);
}
}
2.Androidの実装方法
Android プロジェクト内に MailService クラスを配置します。
注意点が3つあります。
(1)intent.SetType("message/rfc822"); の記述を先頭で記述すると動作しませんでした。
(2)intent.SetData(Android.Net.Uri.Parse("mailto:" + to)); の記述をするほうが対応メーラーが広がるそうです。
(3)添付ファイルを付ける場合は、Android.Net.Uri.FromFile で添付することがより多くのメーラーとの相性が良くなるらしいです。
※Android7 以降はFileProviderを使用してファイルパスを Content:// で渡すことが必須となりました。
MailService.cs
using System;
using Android.Content;
using Xamarin.Forms;
using AppName.Services;
using AppName.Droid.Services;
[assembly: Dependency(typeof(MailService))]
namespace AppName.Droid.Services
{
public class MailService : IMailService
{
public bool StartMailer(string title, string body, string[] to, string[] cc, string[] bcc, string filePath, ref string err)
{
try
{
//初期化
err = String.Empty;
var intent = new Intent();
//アクションにACTION_SENDを指定して暗黙的インテントを呼び出すことで、
//インストールされているアプリで対応可能なものが列挙されます。
intent.SetAction(Intent.ActionSend);
intent.AddFlags(ActivityFlags.NewTask);
//項目セット
intent.SetData(Android.Net.Uri.Parse("mailto:" + to));
if (to != null && to.Length > 0)
{
intent.PutExtra(Intent.ExtraEmail, to);
}
if (cc != null && cc.Length > 0)
{
intent.PutExtra(Intent.ExtraCc, cc);
}
if (bcc != null && bcc.Length > 0)
{
intent.PutExtra(Intent.ExtraBcc, bcc);
}
intent.PutExtra(Intent.ExtraSubject, title);
intent.PutExtra(Intent.ExtraText, body);
if (String.IsNullOrEmpty(filePath))
{
//ファイル添付なし
//intent.SetType("text/plain");
intent.SetType("message/rfc822");
}
else
{
//ファイル添付あり
intent.SetType("message/rfc822");
//Androidバージョンにおけるファイルパスの対応
Java.IO.File sendFile = new Java.IO.File(filePath);
Android.Net.Uri uri = null;
if ((int)Build.VERSION.SdkInt < (int)(BuildVersionCodes.N))
{
//Android6.0以前
uri = Android.Net.Uri.FromFile(sendFile);
}
else
{
//Android7.0以降
uri = Android.Support.V4.Content.FileProvider.GetUriForFile(
Forms.Context,
Forms.Context.PackageName + ".fileprovider",
sendFile
);
}
}
//メーラー起動
Forms.Context.StartActivity(intent);
}
catch (Exception ex)
{
err = ex.Message;
Console.WriteLine(ex.Message + System.Environment.NewLine + ex.StackTrace);
return false;
}
return true;
}
}
}
3.iOSの実装方法
iOS プロジェクト内に MailService クラスを配置します。
MailService.cs
using Foundation;
using UIKit;
using MessageUI;
using Xamarin.Forms;
using AppName.iOS.Services;
using AppName.Services;
[assembly: Dependency(typeof(MailService))]
namespace AppName.iOS.Services
{
public class MailService : IMailService
{
public bool StartMailer(string title, string body, string[] to, string[] cc, string[] bcc, string filePath, ref string err)
{
//初期化
err = String.Empty;
string ret = String.Empty;
if (!MFMailComposeViewController.CanSendMail)
{//メール送信が可能かどうかの確認
err = "この端末はメールが送信可能な状態にありません。";
return false ; //メール送信不能
}
var mail = new MFMailComposeViewController();//インスタンスの生成
//項目セット
if (to != null && to.Length > 0)
{
mail.SetToRecipients(to);
}
if (cc != null && cc.Length > 0)
{
mail.SetCcRecipients(cc);
}
if (bcc != null && bcc.Length > 0)
{
mail.SetBccRecipients(bcc);
}
mail.SetSubject(title);
mail.SetMessageBody(body, false);
if (!String.IsNullOrEmpty(filePath))
{
//ファイル添付あり
//拡張子
string extention = System.IO.Path.GetExtension(filePath.ToLower()).Replace(".", "");
if (String.IsNullOrEmpty(extention))
{
//拡張子が取得できない場合はテキストで開く
extention = "txt";
}
//mime type
string mimetype = MimeTypeUtility.GetMimeType(extention);
NSData data = NSData.FromFile(filePath);
mail.AddAttachmentData(data, mimetype, System.IO.Path.GetFileName(filePath));
}
mail.Finished += (o, args) => {
//送信処理終了時のイベント
ret = args.Result.ToString(); // srgs.Result:戻り値
args.Controller.DismissViewController(true, null); //Eメール画面の消去
};
//メーラー起動
var view = UIApplication.SharedApplication.KeyWindow.RootViewController;
view.PresentViewController(mail, true, null);
err = ret;
return true;
}
}
}
※拡張子から MimeType を取得する方法(MimeTypeUtility.GetMimeType)につきましては以下の URL にてご紹介しております。
https://itblog.dynaspo.com/blog-entry-175.html
4.使用方法
PCL プロジェクトの中の任意のページに記述します。
Test.xaml.cs
using AppName.Services;
using Xamarin.Forms;
public partial class TestPage : ContentPage
{
async void OnSendMailButtonPress()
{
string errMsg = String.Empty;
DependencyService.Get<IMailService>().StartMailer("タイトル", "本文", null, null, null, this.txtFilePath, ref errMsg);
if (String.IsNullOrEmpty(errMsg))
{
await this.DisplayAlert("メール送信完了",
"メール送信完了しました。" + System.Environment.NewLine +
errMsg, "OK");
}
else
{
await this.DisplayAlert("メール送信失敗",
"メールが送信できませんでした。" + System.Environment.NewLine +
errMsg, "OK");
}
}
}
SMS を送信したい場合は、次の記事「Xamarin.FormsでSMSを送信する方法」をご参考ください。
※2017/10/26追記
説明文を追加しました。
最後までお読みいただきありがとうございます。
当ブログの内容をまとめた Xamarin逆引きメニュー は以下のURLからご覧になれます。
https://itblog.dynaspo.com/blog-entry-81.html
- 関連記事
-