C#からOutlookメールを操作する。

## はじめに
本記事はC#からOutlookメールを操作するための基本的な情報をまとめることを目的としています。
​
## 準備
Officeをインストールしたときに自動でインストールされるMicrosoft Outlook 16.0 Object Libraryコンポーネントを対象のプロジェクトの参照に追加します。
VisualStudioのプロジェクトの参照の右クリックメニューから参照の追加を選択します。以下の画面が出てくるので、Microsoft Outlook 16.0 Object Libraryコンポーネントを選択し、OKを押します。
![Outlook参照の追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562946/3024ac8c-a4ec-cb41-253c-c379f0704460.png)


すると、Microsoft.Office.Interop.Outlook名前空間をインポートできます。
そして、メールの操作を行いたいクラスで、

```c#
using Outlook = Microsoft.Office.Interop.Outlook;
```

このようにusingを宣言することで、Outlookメール様々な機能を使えるようになります。
このusingステートメントは関数の直前に置くことはできないので、Class宣言の前に追加しておきましょう。
ここからの説明は上記のように名前空間にエイリアスを付けた状態で説明します。
​
## メールを作成する
早速メールを作成してみましょう。
とても簡単です。以下、サンプルコードです。

```c#
/// <summary>
/// メールの送信画面の作成
/// </summary>
public void CreateMail()
{
    // outlookメールの立ち上げ
    var application = new Outlook.Application();
	MailItem mailItem = application.CreateItem(OlItemType.olMailItem);
	if (mailItem != null)
	{                
        // To
		Recipient to = mailItem.Recipients.Add("XXX@XXX.co.jp");
        to.Type = (int)Outlook.OlMailRecipientType.olTo;
                
        // Cc
        Recipient cc = mailItem.Recipients.Add("YYY@YYY.co.jp");
        cc.Type = (int)Outlook.OlMailRecipientType.olCC;

        // アドレス帳の表示名で表示できる
        mailItem.Recipients.ResolveAll();
​
        // 件名
		mailItem.Subject = "件名";
​
		// 本文
		mailItem.Body = "本文";
​
		// 表示(Displayメソッド引数のtrue/falseでモーダル/モードレスウィンドウを指定して表示できる)
		mailItem.Display(true);
	}
}
```
​
たったこれだけで色々な情報がすでに入った状態のOutlookメールの送信画面を立ち上げることができます。
OutlookのApplicationオブジェクトのインスタンスを生成し、MailItemを作成します。CreateItemメソッドの引数にアイテムタイプを指定することでMailItemを作成できます。
MailItemのプロパティにそれぞれ値を入れて、最後にMailItemのDisplayメソッドを呼んでメールを表示させるだけです。
MailItemのBodyプロパティで設定するメール本文の改行コードについて、CR/LF/CRLFいずれも改行コードとして同じ扱いなのでどれを使用しても構いません。
宛先はMailItemオブジェクトのRecipientsプロパティで全受信者を表すRecipientsコレクションオブジェクトを取得し、RecipientsオブジェクトのAddメソッドで新たな宛先を追加することできます。
そして、ResipientオブジェクトのTypeプロパティを変更することで、ResipientをToやCc、Bccに変更することができます。
また、あらかじめ固定で宛先が決まっている場合はMailItemオブジェクトのToプロパティに直接値を代入すればよいです。複数宛先を追加したい場合、セミコロン区切りのメールアドレスを代入することで設定できます。以下がその例です。

```c#
mailItem.To = "XXX@XXX.co.jp; YYY@YYY.co.jp";
```

## 会議案内を作成する
メールを作成するで説明したこととほぼ同様に作成できます。CreateItemメソッドの引数に```OlItemType.olAppointmentItem```を指定してアイテムタイプをAppointment(予定表)にしてAppointmentItemオブジェクトを作成します。
また、AppointmentItemのMeetingStatusプロパティに、OlMeetingを設定することで会議を予定することができます。
また、メール作成と同様にRecipients.Addメソッドで宛先を追加し、RecipientオブジェクトのTypeで必須出席者か任意出席者に設定できます。
以下がサンプルコードです。

```c#
/// <summary>
/// 会議案内を作成する
/// </summary>
public void CreateAppointment()
{
	var application = new Application();
	AppointmentItem appointmentItem = application.CreateItem(OlItemType.olAppointmentItem);
	if (appointmentItem != null)
	{
		// 会議案内を予定
        // 予定アイテムを会議出席依頼として設定するには、MeetingStatusプロパティをolMeetingに設定する必要がある。
		appointmentItem.MeetingStatus = OlMeetingStatus.olMeeting;
				
		// 件名
		appointmentItem.Subject = "件名";
​
		// 本文
		appointmentItem.Body = "本文";
​
		// 翌日の9時開始
		appointmentItem.Start = DateTime.Today.AddDays(1) + new TimeSpan(0,9,0);
​
		// 1時間で確保
		appointmentItem.Duration = "60";
​
		// 必須出席者
		Recipient required =
			appointmentItem.Recipients.Add("XXX@XXX.co.jp");
		required.Type =
			(int) OlMeetingRecipientType.olRequired;
		
					
		// 任意出席者	
		Recipient optional =
			appointmentItem.Recipients.Add("YYY@YYY.cp.jp");
		optional.Type =
			(int)OlMeetingRecipientType.olOptional;

        // アドレス帳の表示名で表示できる
        mailItem.Recipients.ResolveAll();
            
		// 表示
		appointmentItem.Display(true);
	}
}	
```

## さいごに
私は思っていたよりも簡単にC#からOutlookを操作できてすごいと感じました。AppointmentItemのプロパティ等を眺めると、予定が競合しているかどうかを確認できたり、アラームが設定できたりと、便利な機能が色々作れそうだなと思いました。
最後までお読みいただき、ありがとうございました。

## 参考サイト
https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.office.interop.outlook?view=outlook-pia
https://docs.microsoft.com/ja-jp/office/client-developer/outlook/pia/how-to-create-a-mail-item-by-using-a-message-template
https://docs.microsoft.com/ja-jp/office/client-developer/outlook/pia/how-to-create-a-meeting-request-add-recipients-and-specify-a-location