WPFでExcelを保存せずにメール添付する完全ガイド|MemoryStreamとClosedXML+MailKit/Graphで解決

WPF(.NET)アプリでレポートや帳票を 物理ドライブに保存せず、そのままメールに添付して送信したい——業務アプリではごく普通の要件です。ところが実装してみると、MemoryStream に書き込めない、送ったはずの添付が空、Attachment に渡したのに添付されない、SmtpClient が通らない……といった“あるある”にぶつかりがちです。本記事は、この問題の本質と最短で解決する実装パターン、運用でハマらないための注意点を実務目線で詳解します。


目次

結論(TL;DR)

  • Excelは ClosedXML 等のストリーム対応ライブラリで作る。
  • workbook.SaveAs(ms) の直後に ms.Position = 0; を必ず実行。
  • 送信は MailKit(または Microsoft Graph)へ移行。System.Net.Mail.SmtpClient は認証要件的に厳しい。
  • 添付の MIME タイプ は application/vnd.openxmlformats-officedocument.spreadsheetml.sheet を明示。
  • ストリームや添付は Dispose管理(using)を徹底。UIは async/await でブロックしない。

状況とよくある課題

やりたいこと

  • WPFのボタン(例:「メール送信」)で、アプリ内で生成したExcelを添付して送信したい。
  • セキュリティポリシー上、物理ファイルを作らずに MemoryStream 上で完結したい。

発生しがちなトラブルの実例

症状ありがちな原因対処
workBook.SaveAs(ms) で例外使っているExcelライブラリがストリーム保存をサポートしていない/ms が書き込み不可
または ms を既にDispose
ClosedXMLなどストリーム対応のライブラリを使う/new MemoryStream() を適切に管理
添付が空/壊れているms.Position を先頭に戻していない/GetBuffer() の使い方誤りms.Position = 0; を必ず実行/ToArray() を使う
Attachment(Stream) で送ったのに添付されない送信前に ms をDispose/MIME未設定/SmtpClient が途中で落ちる送信完了まで ms を生かす/MIMEを明示/MailKit等に移行
SMTP認証で失敗SmtpClient がモダン認証(OAuth2)非対応MailKit + OAuth2 か Microsoft Graph を使用

最も確実な実装パターン:ClosedXML → MemoryStream → MailKit

以下は保存なしでExcelを作成し、そのままメールに添付して送る最短コードです。ClosedXMLはストリーム出力を正式サポートしており、MemoryStreamに対するSaveAsで問題が生じにくいのがメリットです。

using System;
using System.IO;
using System.Threading.Tasks;
using ClosedXML.Excel;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;

public static class MailWithExcel
{
    public static async Task SendAsync()
    {
        // 1) Excel 作成(ClosedXML)
        using var wb = new XLWorkbook();
        var ws = wb.Worksheets.Add("Sheet1");
        ws.Cell("A1").Value = "Hello world!";
        ws.Cell("B2").Value = DateTime.Now;

        using var ms = new MemoryStream();
        wb.SaveAs(ms);        // ストリームに保存
        ms.Position = 0;      // ★必須:先頭に戻す

        // 2) メール作成(MimeKit)
        var message = new MimeMessage();
        message.From.Add(MailboxAddress.Parse("[email protected]"));
        message.To.Add(MailboxAddress.Parse("[email protected]"));
        message.Subject = "レポート送付(保存なし添付)";

        var builder = new BodyBuilder { TextBody = "レポートを添付します。" };

        // 添付:MIMEタイプを明示
        var contentType = new ContentType("application",
            "vnd.openxmlformats-officedocument.spreadsheetml.sheet");

        // メモリ複製を避けたい場合は Stream 版も可だが、ToArray() の方が管理が簡単
        builder.Attachments.Add("Report.xlsx", ms.ToArray(), contentType);

        message.Body = builder.ToMessageBody();

        // 3) 送信(MailKit)
        using var client = new SmtpClient();
        await client.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls);

        // 認証(例:ユーザ名/パスワード)※実運用はOAuth2推奨
        await client.AuthenticateAsync("smtp-user", "smtp-password");

        await client.SendAsync(message);
        await client.DisconnectAsync(true);
    }
}

ポイント

  • ms.Position = 0; を入れないと、添付が空になるか、壊れます。
  • MailKitの BodyBuilder.Attachments.Add() に byte[] を渡すと、送信後に MemoryStream をDisposeしても安全です(内部で必要分を保持)。
  • 添付のMIMEは必ず明示。Excel(.xlsx)は application/vnd.openxmlformats-officedocument.spreadsheetml.sheet。

「保存なし添付」がうまくいかない原因と対策を体系化

失敗ポイント詳細ベストプラクティス
Excel生成ライブラリの選定Interopや一部の古いライブラリは「ファイル保存前提」。
ストリーム保存が曖昧だと例外や壊れた添付になりやすい。
ClosedXML / EPPlus / NPOIなどストリーム保存OKのライブラリを利用。
ストリームの位置SaveAs(ms) 後はストリームの位置が末尾。
そのまま読み出すと0バイト(空添付)。
ms.Position = 0 を必ず行う。
DisposeタイミングAttachment に渡したストリームを先にDisposeすると送信時に読み出せず失敗。送信完了後にDispose。
またはToArray()でバッファを渡す。
MIMEタイプ未指定だと application/octet-stream になり、環境によって扱いが不安定。ExcelのMIMEを明示。
ファイル名拡張子も .xlsx を付ける。
SMTPの認証方式モダン環境はOAuth2必須が主流。SmtpClient は基本認証のみで躓く。MailKit + OAuth2、またはMicrosoft Graphへ移行。

代替:System.Net.Mail(最小構成)の正しい書き方

レガシー互換や社内SMTPでどうしても System.Net.Mail を使う場合の最小コード。認証・運用上はMailKit推奨です。

using System.IO;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using ClosedXML.Excel;

void SendWithSystemNetMail()
{
    using var wb = new XLWorkbook();
    var ws = wb.Worksheets.Add("Data");
    ws.Cell("A1").Value = "保存なしメール添付テスト";

    using var ms = new MemoryStream();
    wb.SaveAs(ms);
    ms.Position = 0; // ★必須

    using var mail = new MailMessage("[email protected]", "[email protected]");
    mail.Subject = "テスト送信";
    mail.Body = "保存無しで添付しています。";

    var ct = new ContentType("application",
        "vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    var attachment = new Attachment(ms, ct);
    attachment.Name = "Report.xlsx"; // ファイル名
    attachment.ContentDisposition.FileName = "Report.xlsx";
    mail.Attachments.Add(attachment);

    using var smtp = new SmtpClient("smtp.example.com", 587)
    {
        EnableSsl = true,
        Credentials = new NetworkCredential("user", "password")
    };
    smtp.Send(mail); // ここでmsはまだ生きている必要がある
}

注意:using(var ms = ...) のスコープを smtp.Send() より外にしてしまうと、送信時にストリームが既に閉じられてエラーになります。必ず送信完了後にDisposeされる構造にしてください。


Microsoft 365に強い:Microsoft Graphで送信(OAuth2)

Microsoft 365(Exchange Online)の場合、SMTPよりもGraph API(/sendMail)が確実でモダンです。WPFなら Azure.Identity の InteractiveBrowserCredential などを使ってトークンを取得し、そのまま添付送信できます。

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using ClosedXML.Excel;
using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Graph.Models;

public static class GraphMailer
{
    public static async Task SendViaGraphAsync()
    {
        // 1) Excel生成 → メモリ
        using var wb = new XLWorkbook();
        var ws = wb.Worksheets.Add("Report");
        ws.Cell("A1").Value = "Graph送信";
        ws.Cell("A2").Value = DateTime.Now;

        using var ms = new MemoryStream();
        wb.SaveAs(ms);
        var bytes = ms.ToArray(); // Graphはbyte[]でOK

        // 2) Graphクライアント(ユーザー委任 /Mail.Send)
        var scopes = new[] { "Mail.Send" };
        var cred = new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions
        {
            TenantId = "common", // またはテナントID
            ClientId = "YOUR-APP-CLIENT-ID",
            RedirectUri = new Uri("http://localhost")
        });
        var graph = new GraphServiceClient(cred, scopes);

        // 3) メッセージ作成(添付:FileAttachment)
        var msg = new Message
        {
            Subject = "Graphで保存なし添付",
            Body = new ItemBody { ContentType = BodyType.Text, Content = "添付をご確認ください。" },
            ToRecipients = new List<Recipient>
            {
                new Recipient { EmailAddress = new EmailAddress { Address = "[email protected]" } }
            },
            Attachments = new List<Attachment>
            {
                new FileAttachment
                {
                    OdataType = "#microsoft.graph.fileAttachment",
                    Name = "Report.xlsx",
                    ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                    ContentBytes = bytes
                }
            }
        };

        await graph.Me.SendMail.PostAsync(new Microsoft.Graph.Users.Item.SendMail.SendMailPostRequestBody
        {
            Message = msg,
            SaveToSentItems = true
        });
    }
}

ポイント

  • Azure AD(Entra ID)アプリ登録で Mail.Send 権限を付与。ユーザー委任なら同意が必要。
  • SMTPの制約やTLS設定に悩まされず、モダン認証一本化ができるため運用が楽です。

使うライブラリ別:ストリーム保存の可否と実装メモ

ライブラリストリーム保存サンプル備考
ClosedXML◎ 対応wb.SaveAs(ms); ms.Position = 0;操作が直感的。レイアウト・書式も簡単。
EPPlus◎ 対応package.SaveAs(ms); ms.Position = 0;商用利用時はライセンスに注意。LicenseContext の設定が必要。
NPOI◎ 対応wb.Write(ms); ms.Position = 0;大規模データで堅実。軽量志向。
Office Interop△ 基本はファイル保存–サーバーサイド非推奨。UIプロセス依存で不安定。

WPF(MVVM)での実装ガイド:UIフリーズを回避する

Excel生成や送信は重い処理です。UIスレッドで同期実行するとフリーズします。非同期(async/await) を徹底し、キャンセル・進捗も考慮しましょう。

// ICommand実装は簡略化
public AsyncRelayCommand SendReportCommand { get; }

public ViewModel()
{
    SendReportCommand = new AsyncRelayCommand(SendReportAsync, CanSend);
}

private bool CanSend() =&gt; !IsBusy;

private async Task SendReportAsync()
{
    try
    {
        IsBusy = true;
        Status = "レポート作成中...";

        // Excel生成→メール送信(上記メソッドを呼ぶだけ)
        await MailWithExcel.SendAsync();

        Status = "送信完了";
    }
    catch (Exception ex)
    {
        Status = "失敗: " + ex.Message;
        // ログ出力
    }
    finally
    {
        IsBusy = false;
    }
}

Tips

  • ユーザーの操作性:プログレス表示、キャンセルボタン、エラーメッセージの整備。
  • 例外の握り潰し禁止:ログ(イベントログやファイル)へ確実に出す。

MailKitを使うなら:プロトコルログで“原因究明が一瞬”

通信失敗時はプロトコルログが有効です。MailKitは簡単に記録できます。

using var logStream = new MemoryStream();
using var logger = new ProtocolLogger(logStream);
using var client = new MailKit.Net.Smtp.SmtpClient(logger);

await client.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls);
// ...
// 送信処理
// ...

// 失敗時:ログ確認
logStream.Position = 0;
using var reader = new StreamReader(logStream);
var protocolText = reader.ReadToEnd();
// ログをファイル出力やアプリ内画面に表示する

大容量・高頻度送信の設計ポイント

  • サイズ上限:SMTPや受信側の上限に注意(本文+Base64エンコードで実体サイズの約1.37倍)。
  • 運用代替:サイズが大きい/頻度が高い場合、OneDrive/SharePointへアップロードしてリンク送信が現実的。
  • メモリ効率:巨大ワークブックは ToArray() での複写コストが無視できない。
    MailKitの MimePart + MimeContent(Stream) でストリームを直接渡す手もある(Dispose順序に注意)。

日本語ファイル名・文字化け対策

  • ファイル名は attachment.Name と ContentDisposition.FileName の両方に設定(System.Net.Mail)。
  • MailKitはRFC2231拡張でエンコードされ、主要メーラーで安定して表示されます。

セキュリティと資格情報の扱い

  • メール資格情報やクライアントシークレットはソースに直書きしない。Windows資格情報マネージャー、ユーザーシークレット、Azure Key Vault等で管理。
  • OAuth2トークンのキャッシュは暗号化して保存。リフレッシュ・失効の扱いを設計。
  • 監査証跡(送信記録)をアプリ側でも保持すると、問い合わせ対応が楽になります。

よくある落とし穴チェックリスト

  1. ms.Position = 0 を忘れていないか。
  2. 送信が終わる前に MemoryStream をDisposeしていないか。
  3. Excelの MIMEタイプ を指定しているか。
  4. SMTPがモダン認証必須の環境で SmtpClient を使い続けていないか。
  5. GetBuffer() をそのまま使って余分なバイトを送っていないか(ToArray() を推奨)。
  6. UIスレッドで同期実行してフリーズしていないか(async 化)。

一時ファイル経由という逃げ道(どうしてもストリーム非対応なら)

特殊要件や使用ライブラリの制約でストリーム保存ができないケースでは、一時ファイルを安全に使う方法もあります。ただし、I/Oコストと情報漏えいリスクが上がるため、可能なら避けましょう。

var tmp = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".xlsx");

try
{
    // ライブラリの都合で一度ファイルに保存
    wb.SaveAs(tmp);

    // 読み込んでMemoryStream化
    byte[] bytes = File.ReadAllBytes(tmp);

    var builder = new BodyBuilder { TextBody = "添付します。" };
    builder.Attachments.Add("Report.xlsx", bytes,
        new ContentType("application", "vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
    // 送信...
}
finally
{
    if (File.Exists(tmp))
    {
        // 確実に削除
        File.Delete(tmp);
    }
}

デバッグとテストのコツ

  • 最初は自分宛に送信して、受信側(Gmail/Outlookなど)で「開けるか/壊れていないか」を確認。
  • 実運用前にサイズ上限・回数制限・送信ドメイン認証(SPF/DKIM/DMARC) の影響を運用部門と事前合意。
  • ログは成功時も残す(後日“届いていない”の問い合わせ時に有効)。

サンプル:ClosedXMLでのExcel整形の基本

using var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("売上");

ws.Cell("A1").Value = "日付";
ws.Cell("B1").Value = "商品";
ws.Cell("C1").Value = "金額";
ws.Range("A1:C1").Style.Font.Bold = true;

// サンプルデータ
for (int i = 0; i < 10; i++)
{
ws.Cell(i + 2, 1).Value = DateTime.Today.AddDays(-i);
ws.Cell(i + 2, 2).Value = "アイテム" + (i + 1);
ws.Cell(i + 2, 3).Value = 1200 + i * 100;
}
ws.Column(1).Style.DateFormat.Format = "yyyy-mm-dd";
ws.Column(3).Style.NumberFormat.Format = "#,##0";
ws.Columns().AdjustToContents();

// 以降は SaveAs(ms) → メール添付へ 

運用で差が出る小ワザ集

  • 件名・本文に識別子(対象日付、レポート種別、部署名など)を入れて検索性を高める。
  • 送信履歴テーブル(宛先・件名・時刻・結果・メッセージID)をDBに残す。
  • リトライ戦略:一時的な接続エラーは指数バックオフで再送。二重送信防止のキー設計。
  • 例外のユーザー向けメッセージは平易な日本語で(技術詳細はログへ)。

まとめ

WPFアプリから「ファイルを保存せずに」Excelをメール添付するには、ストリーム対応のExcelライブラリ(ClosedXML等)と、モダンな送信手段(MailKitまたはMicrosoft Graph)を組み合わせるのが最短・最安定です。特に、ms.Position = 0 の徹底、MIMEタイプの明示、Disposeの順序管理は“壊れた添付”や“添付なし”を未然に防ぐ必須要件です。認証面ではモダン化が進んでいるため、実運用ではOAuth2への移行を前提に設計しておくと将来の保守コストが下がります。


付録:トラブルシューティング早見表

現象即確認するポイント対応
添付が0バイトms.Position が0か?ms.Position = 0; を実行。
送信時に例外ストリームを先にDisposeしていないか?送信完了まで ms を生かす/ToArray() を使う。
受信側で開けないMIMEタイプ/拡張子が正しいか?.xlsx とExcelのMIMEを明示。
SMTP認証が通らないOAuth2が必須か? 基本認証が拒否されていないか?MailKit + OAuth2 または Graphへ移行。

完全版サンプル(ClosedXML + MailKit、WPFから呼び出しやすい形)

using System;
using System.IO;
using System.Threading.Tasks;
using ClosedXML.Excel;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;

public sealed class ExcelMailService
{
private readonly string _smtpHost;
private readonly int _smtpPort;
private readonly string _smtpUser;
private readonly string _smtpPassword;

```
public ExcelMailService(string host, int port, string user, string password)
{
    _smtpHost = host;
    _smtpPort = port;
    _smtpUser = user;
    _smtpPassword = password;
}

public async Task SendReportAsync(string to, string subject)
{
    // Excel生成
    using var wb = new XLWorkbook();
    var ws = wb.Worksheets.Add("Sheet1");
    ws.Cell("A1").Value = "保存無しでExcel添付";
    ws.Cell("A2").Value = DateTime.Now;
    ws.Columns().AdjustToContents();

    using var ms = new MemoryStream();
    wb.SaveAs(ms);
    ms.Position = 0;

    // メール作成
    var message = new MimeMessage();
    message.From.Add(MailboxAddress.Parse("[email protected]"));
    message.To.Add(MailboxAddress.Parse(to));
    message.Subject = subject;

    var builder = new BodyBuilder { TextBody = "添付をご確認ください。" };
    var ct = new ContentType("application",
        "vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    builder.Attachments.Add("Report.xlsx", ms.ToArray(), ct);
    message.Body = builder.ToMessageBody();

    // 送信
    using var client = new SmtpClient();
    await client.ConnectAsync(_smtpHost, _smtpPort, SecureSocketOptions.StartTls);
    await client.AuthenticateAsync(_smtpUser, _smtpPassword);
    await client.SendAsync(message);
    await client.DisconnectAsync(true);
}
```

} 

上記クラスをDIやサービスとしてViewModelから呼び出すだけで、WPFアプリに綺麗に組み込めます。


最後に:この手順で“もう迷わない”

  • ExcelはClosedXML、保存はMemoryStream、位置リセットが必須。
  • 送信はMailKit(またはGraph)、MIME・Dispose・非同期で安定運用。
  • サイズ・認証・ログ・UI応答性を最初から設計に入れる。

参考の実装差分(メール送信手段の比較)

手段強み弱み向いているケース
MailKit(SMTP)実装が簡単、ログ豊富、OAuth2対応可SMTP上限・運用ポリシーに左右される既存SMTPがある、移行コストを抑えたい
Microsoft GraphMicrosoft 365と親和性高、モダン認証、監査性アプリ登録・権限同意など初期設定が必要Exchange Online主体、将来の運用を見据える
System.Net.Mail(レガシー)レガシー互換モダン認証非対応、将来性に乏しい閉域・オンプレ専用や一時的な互換維持

FAQ(現場でよく聞かれる質問)

Q. SaveAs(ms) で「書き込みできません」の例外が出ます。
A. ms が読み取り専用でないか、または使用ライブラリがストリーム保存を未サポートの可能性。ClosedXML/EPPlus/NPOI等に切り替えてください。ms を new MemoryStream() で生成し直して、他のコードで閉じていないかも確認。

Q. 添付ファイルが空になります。
A. ほぼ確実に ms.Position = 0 忘れ。
または送信前に ms をDisposeしているか、GetBuffer() を使って余計な領域を送っている可能性。

Q. Gmail/Microsoft 365 で認証に失敗します。
A. 環境側で基本認証が封じられているケースが多いです。MailKit + OAuth2、またはMicrosoft Graphへの移行を検討してください。

Q. 日本語ファイル名が文字化けします。
A. System.Net.Mailの場合は Name と ContentDisposition.FileName を両方設定。MailKitは自動でRFCに沿ったエンコードを行うため安定します。


チェックサンプル:NPOI/EPPlusでの保存なし添付(抜粋)

NPOI

using NPOI.XSSF.UserModel;

var wb = new XSSFWorkbook();
var sheet = wb.CreateSheet("Sheet1");
var row = sheet.CreateRow(0);
row.CreateCell(0).SetCellValue("NPOI");

// 保存なし
using var ms = new MemoryStream();
wb.Write(ms, true);
ms.Position = 0;
// 以降はMailKitで送信(同様) 

EPPlus

using OfficeOpenXml;

// EPPlus では事前にライセンスコンテキスト設定が必要な場合あり
// ExcelPackage.LicenseContext = LicenseContext.NonCommercial;

using var package = new ExcelPackage();
var ws = package.Workbook.Worksheets.Add("Sheet1");
ws.Cells["A1"].Value = "EPPlus";

using var ms = new MemoryStream();
package.SaveAs(ms);
ms.Position = 0;
// 以降はMailKitで送信(同様) 

実装テンプレ・貼り付け用(ClosedXML + MailKit)

最初の実装を素早く形にしたい場合は、以下をそのままプロジェクトに追加して呼び出せば動きます。

public class ReportMailer
{
    private readonly string _host; private readonly int _port;
    private readonly string _user; private readonly string _pass;

    public ReportMailer(string host, int port, string user, string pass)
    { _host = host; _port = port; _user = user; _pass = pass; }

    public async Task SendAsync(string to)
    {
        using var wb = new ClosedXML.Excel.XLWorkbook();
        var ws = wb.Worksheets.Add("Report");
        ws.Cell("A1").Value = "保存なしメール添付";
        ws.Cell("A2").Value = DateTime.Now;
        ws.Columns().AdjustToContents();

        using var ms = new MemoryStream();
        wb.SaveAs(ms); ms.Position = 0;

        var message = new MimeMessage();
        message.From.Add(MailboxAddress.Parse("[email protected]"));
        message.To.Add(MailboxAddress.Parse(to));
        message.Subject = "保存なし添付のサンプル";

        var builder = new BodyBuilder { TextBody = "添付をご確認ください。" };
        var ct = new ContentType("application","vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        builder.Attachments.Add("Report.xlsx", ms.ToArray(), ct);
        message.Body = builder.ToMessageBody();

        using var client = new MailKit.Net.Smtp.SmtpClient();
        await client.ConnectAsync(_host, _port, SecureSocketOptions.StartTls);
        await client.AuthenticateAsync(_user, _pass);
        await client.SendAsync(message);
        await client.DisconnectAsync(true);
    }
}

WPFのボタンハンドラやコマンドから await new ReportMailer(...).SendAsync("[email protected]"); と呼ぶだけでOKです。


これで“ファイルを保存せずに”送る要件はクリアできる

本記事のとおりに進めれば、物理ファイルを一切残さず、添付が壊れない、モダン認証に対応した堅牢な実装を短時間で組み込めます。あとは、業務要件に合わせてExcelのレイアウトや本文、エラーハンドリングを肉付けすれば完成です。


付記:最低限のチェックポイント(再掲)

  • ClosedXMLなどストリーム対応ライブラリで生成する。
  • ms.Position = 0 を忘れない。
  • MIMEタイプはExcelのものを指定。
  • 送信はMailKit/Graphに寄せ、Dispose順序と非同期を守る。

以上、WPFアプリで「保存なし」でExcelをメール添付できない問題の原因の見極め→正しいパターン→運用の勘所までを一気通貫で整理しました。現場の実装にそのまま活かしてください。


この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次