メール受信

Similar documents
ICONファイルフォーマット

正規表現応用

メール送信

ファイル操作

グラフィックス

プロセス間通信

ファイル操作-バイナリファイル

ファイル操作-インターネットキャッシュ

データアダプタ概要

Userコントロール

Visual Basic 資料 電脳梁山泊烏賊塾 コレクション初期化子 コレクション初期化子 初めに.NET 版の Visual Basic では 其れ迄の Visual Basic 6.0 とは異なり 下記の例の様に変数宣言の構文に 初期値を代入する式が書ける様に成った 其の際 1 の様に単一の値

VB実用Ⅲ⑩ フリーデータベースⅡ

プラグイン

VB.NET解説

NotifyIconコントロール

ListViewコントロール

ハッシュテーブル

64bit環境で32bitコンポーネントの利用

構造体

VB 資料 電脳梁山泊烏賊塾 音声認識 System.Speech の利用 System.Speech に依るディクテーション ( 音声を文字列化 ).NetFramework3.0 以上 (Visual Studio 2010 以降 ) では 標準で System.Speech が用意されて居るの

mySQLの利用

DAOの利用

データベースプログラミング


チャットアプリ

ファイル監視

正規表現概要

PYTHON 資料 電脳梁山泊烏賊塾 PYTHON 入門 文字列 文字列リテラル プログラムの中で文字列を表す方法は幾つか有るが 基本的な方法は下記の 2 種で有る 対象と成る文字の集まりをダブルクオーテーション ( " ) で囲うか シングルクオーテーション ( ' ) で囲う PYTHON3 "

電子メール グループ7 宇賀一登 小椋智泰 久岡敬司 矢野川真帆 1

SOC Report

ルーレットプログラム

VB実用⑦ エクセル操作Ⅰ

Microsoft Word - WebMail.docx

E-Post BossCheck Server 運用マニュアル&事例集

3-1 SPIRIT Gmail を使う メールアドレスの仕組み 自分のメールアドレスを確かめる V-Campus では V-Campus ID を利用したメールアドレスが 一人ひとりに用意されています メールアドレスとは 電子メールの利用者を識別するための宛名にあたるものです V-Campus で

1. メールソフトの設定 Windows 10 Microsoft Windows 10 の メール アプリで POP メールの設定を行う方法をご案内いたします 設定を始める前に あらかじめ メールアドレスの登録を行ってください 重要事項 Windows10 のメールアプリで CCNet のメールを

メール設定

Mailman管理者マニュアル

学校法人 近畿大学 殿

ウィンドウ操作 応用

大阪大学キャンパスメールサービスの利用開始方法

メール誤送信対策<利用者編> ご利用の手引き

IE5及びOE5の設定

Socketクラス

VB.NET解説

1.POP3S および SMTP 認証 1 Outlook2016 を起動します 2 Outlook2016 へようこそ ウィンドウが表示されますので 次へ ボタンを クリックします メールアカウントの追加を行う場合や Outlook2016 へようこそ ウィンドウが表示されない場合は 以下の手順を

在学生向けメールサービス

Outlook Express 6 の場合 (Windows XP) Outlook Express 6 の場合 (Windows XP) Windows XP に付属する Outlook Express 6 に αweb のメールアカウントを追加する方法についてご案内します 1 スタート をクリッ

KDDI ビジネスメール メーラー設定ガイド Ver.1.01 Copyright 2013, KDDI Corporation All rights reserved 1

アカウント管理 アカウント管理 利用者のメールアカウントの追加 編集ができます また パスワード ( 管理者 利用者 ) の変更も可能です アカウント管理画面を表示する 利用者のメールアカウントを登録するための画面は 以下の方法で表示します 1 管理者メニューを表示し アカウント管理 をクリックしま

Microsoft PowerPoint - パソコン講習会資料(3)メール ppt

よくある質問 Q1. 署名付きメールを受信後 署名アイコンをクリックしてメッセージの作成者から正常に送信されていることを確認しましたが 取り消し状態 に デジタル ID の確認が無効になっています と表示されました (Outlook Express6 Windows Mail) 初期設定では 証明書

<4D F736F F D2089E696CA8F4390B35F B838B CA816A>

アルファメール 移行設定の手引き Outlook2016

PYTHON 資料 電脳梁山泊烏賊塾 PYTHON 入門 関数とメソッド 関数とメソッド Python には関数 (function) とメソッド (method) が有る モジュール内に def で定義されて居る物が関数 クラス内に def で定義されて居る物がメソッドに成る ( 正確にはクラスが

WEBシステムのセキュリティ技術

グラフィックス 目次

Windows Liveメールの設定

ブロック パニック

MS Office オートメーション

<4D F736F F D208BD98B7D D B838B835A DD92E8834B C52E646F63>

PowerPoint プレゼンテーション

C 資料 電脳梁山泊烏賊塾 ファイルの入出力 C++ のバイナリファイル入出力 初めに 此処では Visual Studio 2017 を起動し 新しいプロジェクトで Visual C++ の Windows デスクトップを選択し Windows コンソールアプリケーションを作成する

目次 移行前の作業 3 ステップ1: 移行元サービス メールソフトの設定変更 3 ステップ2: アルファメール2 メールソフトの設定追加 6 ステップ3: アルファメール2 サーバへの接続テスト 11 ステップ4: 管理者へ完了報告 11 移行完了後の作業 14 作業の流れ 14 ステップ1: メー

Packet Tracer: 拡張 ACL の設定 : シナリオ 1 トポロジ アドレステーブル R1 デバイスインターフェイス IP アドレスサブネットマスクデフォルトゲートウェイ G0/ N/A G0/

大阪大学キャンパスメールサービスの利用開始方法

FW ファイルアップロード ダウンロード機能利用ガイド Version 年 9 月 21 日富士通株式会社 i All Right Reserved, Copyright FUJITSU LIMITED

公立大学法人首都大学東京

10 完了 をクリック 13 このサーバーは認証が必要 をチェックして 設定 をクリック Windows メール Windows Vista に標準のメールソフト Windows メール の設定方法を説明します 1 スタート から 電子メール Windows メール をクリック 11 続いて設定ファ

Microsoft Word - Activ 利用の手引きVer2.0.doc

2. 総合情報センターホームページからアクセス 総合情報センターホームページ ( 左上にある Web メール をクリ ックします 2015 年 3 月 5 日 ( 木 ) までは現在のメールシステムが表示されます Web ブラウザから直接アクセ

目次 1. 教育ネットひむかファイル転送サービスについて ファイル転送サービスの利用方法 ファイル転送サービスを利用する ( ひむか内 ) ファイル転送サービスへのログイン ひむか内 PCでファイルを送受信する

認証システムのパスワード変更方法

I N D E X リダイレクト画面投稿手順 リダイレクト画面投稿手順 2 1 管理画面にログイン 2 右上の + 追加 を押す メールサービスのご利用について 4 メールソフト設定方法 ご利用のバージョンにより 画面や設定項目が異なる場

スライド 1

グラフィックス 目次


AIR-EDGE: Windows2000 ダイヤルアップ接続の設定方法

MultiStageマニュアル_メール設定編

アルファメールプレミア 移行設定の手引き Outlook2016

ビジネスサーバ設定マニュアルメール設定篇(VPS・Pro)

登録手順 1 の 2 Microsoft Outlook 2013 スタートアップ 参考 スタートアップ画面が表示されない場合 Microsoft Outlook 2013 の起動画面から [ ファイル ] タブを選択し [ 情報 ] をクリックします アカウント情報から [ アカウントの追加 ]

Office365  Outlook

NeoMail(Webメールのご利用方法)

ファイル宅配便サービス 利用マニュアル

Microsoft PowerPoint - メールソフト設定方法マニュアル_ver.1.5.ppt

9. システム設定 9-1 ネットワーク設定 itmはインターネットを経由して遠隔地から操作を行ったり 異常が発生したときに電子メールで連絡を受け取ることが可能です これらの機能を利用するにはiTM 本体のネットワーク設定が必要になります 設定の手順を説明します 1. メニューリスト画面のシステム設

Microsoft PowerPoint pptx

登録手順 1 の 2 Microsoft Outlook 2010 スタートアップ 参考 スタートアップ画面が表示されない場合 Microsoft Outlook 2010 の起動画面から [ ファイル ] タブを選択し [ 情報 ] をクリックします [ アカウント設定 ] [ アカウント設定 (

Java Scriptプログラミング入門 3.6~ 茨城大学工学部情報工学科 08T4018Y 小幡智裕

Microsoft Excel操作

メール送信テストツール手順書

メールデータ移行手順

MISAO with WPF

C 資料 電脳梁山泊烏賊塾 構造体 C++ の構造体 初めに 此処では Visual Studio 2017 を起動し 新しいプロジェクトで Visual C++ の Windows デスクトップを選択し Windows コンソールアプリケーションを作成する 定義と変数宣言 C++ に

GUIプログラムⅣ

2019/7/25 更新 2.2. メーラー設定 (IMAP 設定 ) この項目ではメールソフトで IMAP にて受信ができるように設定をする手順を説明します 事前にマニュアル 1.4 POP/IMAP 許可設定 1.5 メーラー (Outlook 等 ) を使う場合の設定 を行っている必要がありま

<4D F736F F D B B90DD92E8837D836A B5F E302E646F63>

大阪大学キャンパスメールサービスの利用開始方法

Office365 AL-Mail

Transcription:

メール.NET で POP サーバからメールを受信する方法 初めに.NET Framework 1.0 1.1 にはメールを送信する為の System.Web.Mail.SmtpMail クラスが用意されて居る.NET Framework 2.0 には System.Net.Mail.SmtpClient クラスが用意されて居る ( 猶 2.0 にも System.Web.Mail.SmtpMail クラスは有るが System.Net.Mail.SmtpClient クラスの使用が推奨されて居る ) 併し 残念乍 メールを受信するクラスは用意されて居ない 其処で 此処では TcpClient クラスを使用して 直接メールサーバからメールを受信する方法を解説する 併せて 受信したメールのヘッダ部分から Subject From To 等のヘッダ情報を取得したり 添付ファイルを取り出したりする方法に付いても解説する 必要な環境 サンプルは Visual Studio.NET 2003 で作成され.NET Framework 1.1 で動作確認をして居る 亦 Visual Studio 2005.NET Framework 2.0 での動作も確認して居る インターネットメールの仕組み インターネットメールは SMTP と呼ばれるプロトコルを使ってインターネット内を配送されて居る SMTP は Simple Mail Transfer Protocol の頭文字で 文字通り単純なメール転送プロトコルと成って居る 此処では SMTP の詳細に付いては省略するが SMTP は RFC 2821 等に解説されて居る 前述の様に メールは SMTP を使用して配送される訳だが SMTP に依って配送されるのは SMTP サーバ迄で有る 個々のユーザー迄配送する仕組みは特に無い 実世界に例えると 総てのメールは郵便局止めに成って居て 各家庭や事務所の郵便ポスト迄は配達して下れないと謂う事に成る 其れでは何うするかと謂うと メールを受け取り度い人が夫々れ郵便局迄取りに行く事に成る メーラー メールユーザーエージェント (Mail User Agent:MUA) 等と呼ばれる Outlook Express Outlook 2003 Mozilla Thunderbird Becky! と謂うインターネットメール用のソフトウェアが有るが 此等は孰れも定期的に郵便局 ( メールサーバ ) にメールが届いて居るか何うかを確認し 必要に応じてメールを取りに行く様に成って居る 此の時に使われるプロトコルの代表的な物が POP で有る POP は Post Office Protocol の頭文字で 文字通り 郵便局プロトコル で有る 現在一般的に使われて居る POP はバージョン 3 と成って居るので POP3 と表記される事も良く有る ( 以下 単に POP と表記するが POP3 の事と考えて問題無い ) POP に付いては RFC 1939 で解説されて居る 猶 インターネットメールは SMTP と POP を使わなくては成らないと謂う訳では無い POP より高機能な IMAP(Internet Message Access Protocol) と謂うプロトコルも有る (RFC 2060) 亦 SMTP で配送されたメールをハードディスクにファイルと仕て保存して 其れをテキストエディタで閲覧すると謂う事も可能で有る ( 勿論 其の様な事が出来るメールサーバを用意する必要が有る ) 此の様に インターネットメールの配送に SMTP が使われるのは粗確実だが SMTP で配送された後のメールを何の様に扱うかは非常に自由度が高い仕組みと成って居た 併し インターネットサービスプロバイダや企業のメールサーバの様に多数の人にメールサービスを提供する場合は 統一された手法が無いと不便なので 現在ではメールの送信には SMTP を メールの受信には POP を使用するのが一般的に成って居る ( 勿論 Web メールと呼ばれる様な ブラウザ上で而巳メールサービスを提供して居る場合は除く ) 亦 メーラーも粗例外無く SMTP と POP をサポートして居ると謂っても良い状況に成って居る -1-

RFC とは :RFC は Request For Comment の頭文字で インターネットに関連するさまざまな技術の仕様等に付いてまとめられた文書の事で有る RFC には番号が付けられていて RFC 2821 は SMTP の仕様 RFC 2616 は HTTP の仕様等と成って居る 中には RFC 1149( 鳥を使って IP データを送受信する事に関する仕様 ) の様にジョーク RFC も存在する 改訂版が出る場合は新しい番号が振られて別の文書と仕て公開されるのが通常で有る SMTP の場合 最初の RFC は 821 其の後の改訂版は 2821 と成って居る RFC の文書は英語で書かれて居るが 主要な RFC に付いては日本語訳を公開して居る場合も有るので検索してみて下さい メール受信時に特定の処理を行うには 特定のメールアドレスにメールが届いた時に 其のメールを自動的に受信して何等かの処理を行う様なシステムを作成するには 次の様な方法が考えられる メールサーバの機能を使う メーラーの機能を使う POP で受信する メールサーバの機能を使う メールサーバ ( 正確には SMTP サーバ ) には メールが届いた時に外部プログラムを起動すると謂う機能を持つ物が有る 此の機能を使って メール受信時に処理を行うシステムを作成する事が出来る メーリングリストと謂うの物が存在するが メーリングリストでは 或るメールアドレスにメールを送ると 予め登録された会員全員に其のメールが自動的に配送される 此の様なメーリングリスト機能は メールサーバにメーリングリスト処理を行う外部プログラムを登録して実現されて居る場合が多く有る 此の外部プログラム起動方式は メール受信時に直ぐ様 外部プログラムが呼び出されるのが一般的だし 必要な時に必要な処理丈を行う様に出来る 当然 レスポンスの面でも メールサーバに与える負荷の面でも 優れたシステムに出来る可能性が高いと謂える 併し 外部プログラムの登録にはメールサーバの設定を変更する必要が有り 誤った外部プログラムを登録した場合は メールサービス自体を使用不能に陥らせる危険性も有る 此の設定変更を行うには メールサーバの管理者か其れに匹敵する権限が必要だし 既存のメールサーバに対して設定を行う場合は 細心の注意を仕て作業する必要が有る 其の為 残念乍 誰にでも出来る方法とは謂えない 特にインターネットサービスプロバイダのメールサービスを使用して居る場合は 外部プログラムを登録する事は出来ないと考えた方が良いと思う 此の方法の場合 上記の理由に依り 自分の管理下に有るメールサーバが必要に成る 亦 何の様な事が出来るのか 何の様な外部プログラムを作れば良いのかは 使用するメールサーバに依り変わる メーラーの機能を使う メーラーに依っては プラグインの様な形で機能を拡張 追加したり マクロ言語が搭載されて居たりする 此等の機能を使ってメール受信時の処理を作り込む事が出来る場合が有る 旨く使えば簡単に目的を実現出来る場合も有ると思うが 何の様な事が出来 何の様にすれば良いのかは 完全にメーラーに依存するので 此処では解説しない POP で受信する 本資料で解説する方法で有る メールサーバに TCP で接続し POP を使用してメールを受信する 此の方法は 上記の メールサーバの機能を使う の様な手法と違い インターネットを使用してメール -2-

サーバに接続出来る環境で有れば 何処でも実行する事が出来る メーラーのメール受信処理而巳を自分で実装して実行して居るのと変わらない 実際 メールサーバに取っては メーラーからのアクセスと区別が付かないで有ろう 此の方法の欠点は 即時性に欠ける事で有る POP は メールサーバにメールが届いて居るかを此方から問い合わせる様なプロトコルと成って居る 殆どのメーラーには 新着メールのチェック間隔 の様な設定項目が有って 何の程度の間隔でメールサーバに問い合わせに行くのかを設定出来る様に成って居る 仮に 5 分とすると メールが送られて来てから最大 5 分は遅延する事に成る 間隔を短くすれば即時性は高まるが 極端に短い間隔にすると メールサーバの負荷を高める事にも成り兼ねないので避けた方が良い インターネットメールは 元々即時性が保障された仕組みでは無い メールが直ぐに届く事も有るが 少し時間が懸かる事も普通に有る 従って 此の即時性に欠けると謂う点は 余り問題に成らない事が多いかと思う 逆に問題に成る様な場合は メールを使うと謂う事自体を見直す必要が有る POP でメールを受信する手順 サンプルソースコードに含まれる PopClient クラスは POP を使用してメールサーバからメールを受信するクラスで有る 以下 主要部分に付いて解説する 1. POP サーバとの接続 POP サーバは 通常 TCP の 110 番ポートで待ち受けして居る 其処に TcpClient で接続する 此の処理は PopClient のコンストラクタで行われて居る Visual Basic Public Sub New(ByVal hostname As String, ByVal port As Integer) ' サーバと接続 Me.tcp = New TcpClient(hostname, port) Me.reader = New StreamReader(Me.tcp.GetStream(), Encoding.ASCII) ' オープニング受信 Dim s As String = ReadLine( ) If Not s.startswith("+ok") Then Throw New PopClientException(" 接続時に POP サーバが """ & s & """ を返しました ") End Sub C# public PopClient(string hostname, int port) // サーバと接続 this.tcp = new TcpClient(hostname, port); this.reader = new StreamReader(this.tcp.GetStream( ), Encoding.ASCII); // オープニング受信 string s = ReadLine( ); if (!s.startswith("+ok")) throw new PopClientException(" 接続時に POP サーバが "" + s + " " を返しました "); -3-

上記の ReadLine( ) メソッドは行末迄の 1 行を読み込む private メソッドで有る POP では 8bit ASCII で遣り取りが行われる ( メールが何んな文字コードで書かれて居るかではなく POP 自体の遣り取りの事で有る ) 其の為 Encoding.ASCII を指定した StreamReader を予め作成して置いて テキストの読み込みに使用して居る 猶 POP での行末は必ず CR LF(C# での " r n" ) と決められて居る 亦 ReadLine( ) メソッドは動作確認用に受信したテキストをコンソールに書き出す様にも成って居る POP サーバに接続すると最初にオープニングのテキストが 1 行送られて来る オープニングのテキストの最初は "+OK" で始まる 最短の場合は此の 3 文字と改行丈の場合も有るが 多くの場合は "+OK POP3 server ready." の様なテキストが返される "+OK" より後ろの部分のテキストには特に意味は無い POP サーバの名称やバージョンが記述されて居る事が多い様で有る POP サーバに問題が有る為に使用出来ない場合等は 受信テキストの先頭が "+OK" 以外 ("-ERR") に成る 其の為 上記の様に先頭が "+OK" で無い場合は 例外を投げる様に仕て居る 猶 サンプルソースコードでは s.startswith("+ok") として居るが 必ずしも大文字で有るとは限らない 其の為 s.toupper( ).StartsWith("+OK") の様な判定を行った方が汎用性が増す 以下のログインやリストの取得等 POP サーバから返されるリザルト文字列は 総て同様の事が謂えるので 注意して欲しい 2. ログイン POP サーバを使用するには 通常ユーザー名 パスワードを使用してログインする必要が有る Login( ) メソッドにてログイン処理を行って居る Visual Basic Public Sub Login(ByVal username As String, ByVal password As String) ' ユーザー名送信 SendLine("USER " & username) Dim s As String = ReadLine( ) If Not s.startswith("+ok") Then Throw New PopClientException( _ "USER 送信時に POP サーバが """ & s & """ を返しました ") ' パスワード送信 SendLine("PASS " & password) s = ReadLine( ) If Not s.startswith("+ok") Then Throw New PopClientException( _ "PASS 送信時に POP サーバが """ & s & """ を返しました ") End Sub C# public void Login(string username, string password) // ユーザー名送信 SendLine("USER " + username); string s = ReadLine( ); if (!s.startswith("+ok")) throw new PopClientException( "USER 送信時に POP サーバが "" + s + " " を返しました "); -4-

// パスワード送信 SendLine("PASS " + password); s = ReadLine( ); if (!s.startswith("+ok")) throw new PopClientException( "PASS 送信時に POP サーバが "" + s + " " を返しました "); SendLine( ) メソッドは引数のテキストに改行 (CR LF:C# での " r n") を付加して送信する private メソッドで有る 送信時も 8bit ASCII にする為 Encoding.ASCII.GetBytes( ) を使用して変換した後に送信する様に仕て居る 亦 SendLine( ) メソッドは動作確認用に 送信するテキストをコンソールに書き出す様にも成って居る ログインするには 先ず USER コマンドでユーザー名を送信する 此のコマンドは最初に "USER" 半角スペース 続けてユーザー名 最後に改行 (CR LF) と謂う書式に成って居る ユーザー名 の前は半角スペースを空ける 例えば ユーザー名が abc@example.com の場合は次の様に送信する ユーザー名が正常な場合には "+OK" で始まるテキストが返される オープニングのテキストと同じ様に "+OK" の後には "+OK username is ok." の様に任意のテキストが付いて来る場合も有る ユーザー名が正常では無いと判断された場合は "+OK" 以外 ("-ERR") が返される 次に PASS コマンドでパスワードを送信する 内容はサンプルコードを参照され度い 此の様に POP は 総てテキストの遣り取り丈で構成された 非常に単純で扱い易いプロトコルで有る 殆どの遣り取りは上記の USER コマンドや PASS コマンドの様に コマンドのテキストを送信すると 其れに対する返事のテキストが返って来ると謂う形に成って居る 3. リストの取得 POP にはメールを取得したり削除したりするコマンドが有る POP サーバに複数のメールが溜まって居る場合は 何のメールを取得したり削除したりするのかを番号で指定する 此の番号は予め LIST コマンドで取得して置く必要が有る Public Function GetList( ) As ArrayList ' LIST 送信 SendLine("LIST") Dim s As String = ReadLine( ) Visual Basic -5-

If Not s.startswith("+ok") Then Throw New PopClientException( _ "LIST 送信時に POP サーバが """ & s & """ を返しました ") ' サーバに溜まって居るメールの数を取得 Dim list As ArrayList = New ArrayList Do While True s = ReadLine( ) If s = "." Then ' 終端に到達 Exit Do ' メール番号部分而巳を取り出し格納 Dim p As Integer = s.indexof(" "c) If p > 0 Then s = s.substring(0, p) list.add(s) Loop Return list End Function C# public ArrayList GetList( ) // LIST 送信 SendLine("LIST"); string s = ReadLine( ); if (!s.startswith("+ok")) throw new PopClientException( "LIST 送信時に POP サーバが "" + s + " " を返しました "); // サーバに溜まって居るメールの数を取得 ArrayList list = new ArrayList( ); while (true) s = ReadLine( ); if (s == ".") // 終端に到達 break; // メール番号部分而巳を取り出し格納 int p = s.indexof(' '); if (p > 0) s = s.substring(0, p); list.add(s); return list; -6-

番号のリストを取得するには 先ず LIST コマンドを送信する LIST コマンドには引数は無い為 単に "LIST" と改行而巳を送信する丈で有る 問題が無ければ POP サーバは次の様な一連のテキストを返す 他のコマンドと同様に "+OK" で始まる 1 行のテキストを返す 通常は "+OK" の後に半角スペースで区切って POP サーバに溜まって居るメールの数が記述されて居る 此の例では メールの数は 3 通だった事が解る 何か問題が有ってリストを返せない場合は "-ERR" に成る "+OK" 行の下に続いて居るのがメールのリストで POP サーバに溜まって居るメールの数と同じ行数有る 夫々れの行頭にメールの番号が有り 半角スペースで区切ってオプションのテキストが続く ( 半角スペース以降が無い場合も有る ) リストの最後は "."( ピリオド ) 而巳の行と成る メールの番号は 現在のセッション中丈で有効と成る 上記の例では 1 番 201 番 202 番のメールが有る事に成るが 現在のセッションを切断し 再び接続した時に同じ番号のメールが有るか何うかは解らないし 仮令有ったと仕ても 同じメールで有るとは限らない 従って POP サーバに接続する度に LIST コマンドで番号を取得する必要が有る 今回のサンプルコードでは 取得した番号のリストを ArrayList に格納して返す様に仕て居る 4. メールの取得 メールの番号が解れば メール本体を取得する事が出来る メール本体を取得するには RETR コマンドを使用する Visual Basic Public Function GetMail(ByVal num As String) As String ' RETR 送信 SendLine("RETR " & num) Dim s As String = ReadLine( ) If Not s.startswith("+ok") Then Throw New PopClientException( _ "RETR 送信時に POP サーバが """ & s & """ を返しました ") ' メール取得 Dim sb As StringBuilder = New StringBuilder Do While True s = ReadLine( ) -7-

If s = "." Then ' "." 而巳の場合はメールの終端を表す Exit Do sb.append(s) sb.append(vbcrlf) Loop Return sb.tostring( ) End Function C# public string GetMail(string num) // RETR 送信 SendLine("RETR " + num); string s = ReadLine( ); if (!s.startswith("+ok")) throw new PopClientException( "RETR 送信時に POP サーバが "" + s + " " を返しました "); // メール取得 StringBuilder sb = new StringBuilder( ); while (true) s = ReadLine( ); if (s == ".") // "." 而巳の場合はメールの終端を表す break; sb.append(s); sb.append(" r n"); return sb.tostring( ); RETR コマンドは "RETR"+ 半角スペース +LIST コマンドで取り出したメールの番号の内の 1 つ + 改行 と謂うテキストを送信する POP サーバから返って来るテキストは "+OK" の行 メール本体 "." 而巳の行と成る -8-

メール本体は SMTP で配送されて居る其の儘の形で有る 此の形式は 通常のテキスト形式のメールと殆ど同じで有る 唯一の注意点は行頭に "."( ピリオド ) が有る場合は ".."( ピリオド 2 つ ) と成って居る メール本体の詳細は後述する 5. メールの削除 POP ではメールを取得しても自動的に削除される事は無い メールを削除する場合は DELE コマンドで明示的に削除する必要が有る Visual Basic Public Sub DeleteMail(ByVal num As String) ' DELE 送信 SendLine("DELE " & num) Dim s As String = ReadLine( ) If Not s.startswith("+ok") Then Throw New PopClientException( _ "DELE 送信時に POP サーバが """ & s & """ を返しました ") End Sub C# public void DeleteMail(string num) // DELE 送信 SendLine("DELE " + num); string s = ReadLine( ); if (!s.startswith("+ok")) throw new PopClientException( "DELE 送信時に POP サーバが "" + s + " " を返しました "); メールを削除する時は "DELE"+ 半角スペース +LIST コマンドで取り出したメールの番号の内の 1 つ + 改行 と謂うテキストを送信する 猶 削除したメールを元に戻す事は出来ないので注意を要する 6. クローズ POP との接続を切断する際には QUIT コマンドを使用する DELE コマンドに依るメールの削除等は QUIT コマンドを発行して初めて有効に成ると RFC では既定されて居る 従って 切断時には必ず QUIT コマンドを発行する様にす可きで有る ( 行き成り TCP のセッションを切断するのは 問題が有る ) Public Sub Close( ) ' QUIT 送信 Visual Basic -9-

SendLine("QUIT") Dim s As String = ReadLine( ) If Not s.startswith("+ok") Then Throw New PopClientException( _ "QUIT 送信時に POP サーバが """ & s & """ を返しました ") CType(Me.reader, IDisposable).Dispose( ) Me.reader = Nothing CType(Me.tcp, IDisposable).Dispose( ) Me.tcp = Nothing End Sub C# public void Close( ) // QUIT 送信 SendLine("QUIT"); string s = ReadLine( ); if (!s.startswith("+ok")) throw new PopClientException( "QUIT 送信時に POP サーバが "" + s + " " を返しました "); ((IDisposable)this.reader).Dispose( ); this.reader = null; ((IDisposable)this.tcp).Dispose( ); this.tcp = null; PopClient クラスの使用例 サンプルソースコードの PopMailMain クラスの PopTest( ) メソッドが PopClient クラスの使用例と成って居る Visual Basic ' POP サーバに接続 Dim pop As PopClient = New PopClient("POP サーバ ", 110) ' ログイン pop.login(" ユーザー名 ", " パスワード ") ' POP サーバに溜まって居るメールのリストを取得 Dim list As ArrayList = pop.getlist( ) For i As Integer = 0 To list.count - 1 ' メール本体を取得 Dim mail As String = pop.getmail(ctype(list(i), String)) ' メールを処理 ' メールを POP サーバから取得 pop.deletemail(ctype(list(i), String)) Next ' 切断 pop.close( ) // POP サーバに接続 C# -10-

PopClient pop = new PopClient("POP サーバ ", 110); // ログイン pop.login(" ユーザー名 ", " パスワード "); // POP サーバに溜まって居るメールのリストを取得 ArrayList list = pop.getlist( ); for (int i = 0; i < list.count; ++i) // メール本体を取得 string mail = pop.getmail((string)list[i]); // メールを処理 // メールを POP サーバから取得 pop.deletemail((string)list[i]); // 切断 pop.close( ); 此の使用例では POP に貯まって居る総てのメールを取得して 何等かの処理を行って居る 上記の例では コメント而巳で何等処理も行って居ないが 本来ならメールの内容を解釈し 其れに応じて何等かの処理を行う事に成る 添付のサンプルソースコードでは 処理する代わりに適当なファイル名で保存する様に成って居る 其れでは引き続きメールを解釈する方法に付いて解説する POP から取得したメールの解釈 POP からメールを取得する事が出来たので 続いて取得したメールを解釈する サンプルソースコードの Mail クラスはメールの内容を解釈し 簡単に使用出来る様にするクラスで有る メールの構造 先ずは POP サーバから受け取ったメール本体が何の様な構造に成って居るか観る事にする 猶 下記のメールの実例 ( sample1.txt と sample2.txt ) はサンプルソースコードと共に含めて有る 上記は可成り単純化したメール本体の例で有る メールは ヘッダ部とボディ部に分かれて居る 最初の空行迄がヘッダ部で其れ以降がボディ部で有る 上記の例では 8 行目迄がヘッダ部 以降がボディ部と成る メールヘッダの各項目は 項目名 : 内容 と謂う形式に成って居る ヘッダ部の形式や項目の詳細に付いては RFC 2822 等に纏められて居る To( 宛先 ) From( 差出人 ) Subject( 件名 ) 等の様に比較的解 -11-

り易い名前が付いて居るので 大体の意味は解ると思う 通常は 1 つの項目が 1 行に成るのだが 1 行に収まり切らない場合 ( 上記の例の Subject Content-Type) 継続行の行頭が空白 ( タブか半角スペース ) に成る メールボディは メールの本文で有る 日本語のメールの場合 多くは iso-2022-jp が使われて居る 何の様なコードが使われて居るかはヘッダ部の Content-Type の charset を参照する事に依り解る 猶 上記の例で [ESC] と書かれて居る部分は 実際にはエスケープコード (ASCII コード 1B) で有る 亦 本文 2 行目はピリオド 2 つで始まる行で有る POP から取得した状態では終端と間違うのを防ぐ為にピリオド 2 つに成って居る Content-Type の記述方法や其れに合わせたメールボディの形式は MIME(Multipurpose Internet Mail Extensions) と呼ばれる仕様に纏められて居る 亦 上記の例の From To Subject には日本語が使われて居るが 此の日本語部分の記述方法も MIME に依って決められて居る MIME の仕様は多岐に渡る為 主要な物丈でも次の様に複数に分かれて居る 亦 此等以外にも MIME 関連の RFC は多数有る Part 1 - RFC 2045 Part 2 - RFC 2046 Part 3 - RFC 2047 Part 4 - RFC 4289 Part 5 - RFC 2049 添付ファイル 次に メールに添付ファイルが有る場合を観る事にする 以下の例は GIF 画像が添付されて居るメールの例で有る -12-

此の boundary はメール毎に変わるし 形式も色々な物が有る boundary で分割された部分は 夫々れヘッダ部 ボディ部で構成されて居る 最初のパートは Content-Type が text/plain と成って居るので普通のテキストで有ると解る 此の部分は iso-2022-jp にエンコードされたメール本文で有る 次のパートは image/gif と成って居て 此れが添付された GIF 画像で有る GIF 画像の様なバイナリファイルは 其の儘メールの本文と仕て表現する事が出来ない為 何等かのエンコードを行う必要が有る メールの場合は BASE64 と謂うエンコード方式を使うのが一般的に成って居る エンコード方式は Content-Transfer-Encoding を観ると解る BASE64 は然程複雑なエンコード方式では無いが.NET Framework では Convert.FromBase64String メソッド Convert.ToBase64String メソッドが用意されて居るので簡単に変換する事が出来る サンプルソースコードの Mail クラスは上記の様なメール本体を受け取って解釈する 但し メール本体の構造は非常に柔軟性が有るし 関連する RFC も多岐に亘る Mail クラスは 其の総てに対応して居る訳では無い為 一部解釈出来ないメールも有るかも知れない 併し メールの構造を理解する第一歩には成るかと思う Mail クラスの使用例 Mail クラスの使用例と仕て サンプルのソースコードの PopMailMain クラスの MailTest_Sample1( ) メソッド MailTest_Sample2( ) メソッドを示す MailTest_Sample1( ) メソッドは 添付ファイル等が無い本文テキスト而巳の sample1.txt を解釈する例で有る Visual Basic Private Shared Sub MailTest_Sample1( ) ' テストの為に POP から取得する代わりにファイルから読み込む Dim mailtext As String = Nothing Dim sr As StreamReader = Nothing Try sr = New StreamReader("sample1.txt") mailtext = sr.readtoend( ) Finally If Not sr Is Nothing Then CType(sr, IDisposable).Dispose( ) End Try ' Mail クラスを作成 Dim mymail As Mail = New Mail(mailtext) ' From To Subject を表示 Console.WriteLine(mymail.Header("From")(0)) Console.WriteLine(mymail.Header("To")(0)) Console.WriteLine(mymail.Header("Subject")(0)) Console.WriteLine("--") ' デコードした From To Subject を表示 Console.WriteLine(MailHeader.Decode(mymail.Header("From")(0))) Console.WriteLine(MailHeader.Decode(mymail.Header("To")(0))) Console.WriteLine(MailHeader.Decode(mymail.Header("Subject")(0))) Console.WriteLine("--") ' Content-Type を表示 Console.WriteLine(mymail.Header("Content-Type")(0)) Console.WriteLine("--") -13-

' メール本文を表示 ' 本来は Content-Type の charset を参照してデコードす可きだが ' 此処ではサンプルと仕て iso-2022-jp 固定でデコードする Dim bytes As Byte( ) = Encoding.ASCII.GetBytes(mymail.Body.Text) Dim mymailbody As String = Encoding.GetEncoding("iso-2022-jp").GetString(bytes) Console.WriteLine(" 本文 ") Console.WriteLine(mymailbody) End Sub C# private static void MailTest_Sample1( ) // テストの為に POP から取得する代わりにファイルから読み込む string mailtext = null; using (StreamReader sr = new StreamReader("sample1.txt")) mailtext = sr.readtoend( ); // Mail クラスを作成 Mail mail = new Mail(mailtext); // From To Subject を表示 Console.WriteLine(mail.Header["From"][0]); Console.WriteLine(mail.Header["To"][0]); Console.WriteLine(mail.Header["Subject"][0]); Console.WriteLine("--"); // デコードした From To Subject を表示 Console.WriteLine(MailHeader.Decode(mail.Header["From"][0])); Console.WriteLine(MailHeader.Decode(mail.Header["To"][0])); Console.WriteLine(MailHeader.Decode(mail.Header["Subject"][0])); Console.WriteLine("--"); // Content-Type を表示 Console.WriteLine(mail.Header["Content-Type"][0]); Console.WriteLine("--"); // メール本文を表示 // 本来は Content-Type の charset を参照してデコードす可きだが // 此処ではサンプルとして iso-2022-jp 固定でデコードする byte[] bytes = Encoding.ASCII.GetBytes(mail.Body.Text); string mailbody = Encoding.GetEncoding("iso-2022-jp").GetString(bytes); Console.WriteLine(" 本文 "); Console.WriteLine(mailbody); テストし易くする為に 予め保存して置いた sample1.txt を読み込んで Mail クラスのインスタンスを生成して居る 本来なら POP サーバから取得したメール本体を直接渡す事に成るかと思う 続いて From To Subject の各ヘッダ項目をコンソールに出力して居る mail.header["from"] 等各ヘッダ項目は String のコレクションに成って居る 此れは 複数の宛先に送信したメールは To が複数に成る場合が有る等 ヘッダ項目は複数に成り得る為で有る 上記の例では 最初の要素而巳を出力して居る 亦 全く要素数のチェック等を行って居ないが Subject が無いメール等も有り得るので 本来は 手を抜かずにチェックする必要が有る -14-

上記の出力を観ると解るが 日本語部分は "=?iso-2022-jp?b?gyrcqxc/ljxugyhc?=" の様にエンコードされた儘と成って居る 此れを MailHeader.Decode( ) メソッドを使ってデコードして出力して居る 最後に Content-Type とボディ部のメール本文を出力して居る ボディ部も iso-2022-jp でエンコードされて居るので System.Text.Encoding クラスを使ってデコードする 例では iso-2022-jp に決め打ちで処理して居るが 本来で有れば Content-Type の charset を参照して判断す可きで有る 続く MailTest_Sample2( ) メソッドは GIF ファイルが添付されて居る sample2.txt を解釈する例で有る Private Shared Sub MailTest_Sample2( ) ' 省略 Visual Basic ' 1 つ目のパートの Content-Type メール本文を表示 ' 本来は Content-Type の charset を参照してデコードす可きだが ' 此処ではサンプルとして iso-2022-jp 固定でデコードする Dim part1 As MailMultipart = mymail.body.multiparts(0) Console.WriteLine(" パート 1") Console.WriteLine(part1.Header("Content-Type")(0)) Console.WriteLine("--") Dim bytes As Byte( ) = Encoding.ASCII.GetBytes(part1.Body.Text) Dim mymailbody As String = Encoding.GetEncoding("iso-2022-jp").GetString(bytes) Console.WriteLine(" 本文 ") Console.WriteLine(mymailbody) Console.WriteLine("--") ' 2 つ目のパートの Content-Type を表示し BASE64 をデコードしてファイルと仕て保存する ' 本来は Content-Transfer-Encoding が base64 で有る事を確認したり ' Content-Type の name を参照してファイル名を決めたりす可きだが 此処では省略して居る Dim part2 As MailMultipart = mymail.body.multiparts(1) Console.WriteLine(" パート 2") Console.WriteLine(part2.Header("Content-Type")(0)) Console.WriteLine("--") bytes = Convert.FromBase64String(part2.Body.Text) Dim stm As Stream = Nothing Dim bw As BinaryWriter = Nothing Try stm = File.Open("sample2.gif", FileMode.Create) bw = New BinaryWriter(stm) bw.write(bytes) Finally If Not bw Is Nothing Then CType(bw, IDisposable).Dispose( ) If Not stm Is Nothing Then CType(stm, IDisposable).Dispose( ) End Try Console.WriteLine( " 添付ファイルを保存しました ファイル名は sample2.gif です ") End Sub C# private static void MailTest_Sample2( ) // 省略 -15-

// 1 つ目のパートの Content-Type メール本文を表示 // 本来は Content-Type の charset を参照してデコードす可きだが // 此処ではサンプルとして iso-2022-jp 固定でデコードする MailMultipart part1 = mail.body.multiparts[0]; Console.WriteLine(" パート 1"); Console.WriteLine(part1.Header["Content-Type"][0]); Console.WriteLine("--"); byte[] bytes = Encoding.ASCII.GetBytes(part1.Body.Text); string mailbody = Encoding.GetEncoding("iso-2022-jp").GetString(bytes); Console.WriteLine(" 本文 "); Console.WriteLine(mailbody); Console.WriteLine("--"); // 2 つ目のパートの Content-Type を表示し BASE64 をデコードしてファイルとして保存する // 本来は Content-Transfer-Encoding が base64 で有る事を確認したり // Content-Type の name を参照してファイル名を決めたりす可きだが 此処では省略して居る MailMultipart part2 = mail.body.multiparts[1]; Console.WriteLine(" パート 2"); Console.WriteLine(part2.Header["Content-Type"][0]); Console.WriteLine("--"); bytes = Convert.FromBase64String(part2.Body.Text); using (Stream stm = File.Open("sample2.gif", FileMode.Create)) using (BinaryWriter bw = new BinaryWriter(stm)) bw.write(bytes); Console.WriteLine( " 添付ファイルを保存しました ファイル名は sample2.gif です "); 前半部分は MailTest_Sample1( ) メソッドと殆ど同様なので省略して居る 最初に 1 つ目のパートを iso-2022-jp でデコードして出力して居る 完全に決め打ちで処理して居るが 実際にはパートの数や Content-Type charset の確認等が必要に成る 続いて 2 つ目のパートを System.Convert.FromBase64String( ) メソッドを用いてデコードし sample2.gif と謂うファイル名で保存して居る 此方も実際には Content-Type や Content-Transfer-Encoding 等のチェックが必要で有る 纏め メールの内容を自動的にデータベースに格納する様なシステムを開発する場合 POP サーバからのメールの取得と其のメールの解釈が必要に成る 其の様な場合に本資料が参考に成ればと思う 参考資料 本稿の内容に関連する RFC( 英文 ) で有る RFC 2821 "Simple Mail Transfer Protocol" RFC 1939 "Post Office Protocol - Version 3" RFC 2060 "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1" RFC 2822 "Internet Message Format" RFC 2045 "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies" RFC 2046 "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types" RFC 2047 "MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text" RFC 4289 "Multipurpose Internet Mail Extensions (MIME) Part Four: Registration Procedures" RFC 2049 "Multipurpose Internet Mail Extensions (MIME) Part Five: Conformance Criteria and Examples" http://codezine.jp/a/article.aspx?aid=477-16-

デフォルトメーラーを起動する方法 デフォルトのメーラーを使用してメールの送信を行う場合 Visual Basic 6.0 では Microsoft MAPI Controls 6.0 を使用して居た 一方 Visual Basic.NET では Process クラスの Start メソッドを使用して新規メール作成ウィンドウを表示する 其処で 此処では 図 1 のテキストボックス内のデータを本文の値に設定した新規メール作成ウィンドウを表示する方法を紹介する Process クラスの Start メソッドに mailto: で始まる文字列を指定する事で デフォルトのメーラーを起動する事が出来る メーラーの新規メール作成ウィン図 1 ドウを起動する際 mailto: の後に指定したメールアドレスが宛先欄に記述される 亦 件名 (subject) や本文 (body) 等を記述する場合 宛名 (mailto: メールアドレス ) の後に? で続けて記述する 実装コードは以下の通りで有る Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles Button1.Click Dim strbody As String strbody = textbox1.text Process.Start("mailto:Test@xxx.co.jp?subject= メーラーの起動 &body=" & strbody) End Sub リスト 1 リスト 1 の Process.Start("mailto:Test@xxx.co.jp?subject= メーラーの起動 &body=" & strbody) で 宛先 (mailto:test@xxx.co.jp) メールの件名 (subject= メーラーの起動 ) 本文 (body=strbody: テキストボックス内のデータ ) の値を指定した新規メールウィンドウが表示される 上記を実装し メーラーの起動 ボタン ( 図 1) をクリックすると図 2 が表示される 図 2-17-

上記では 改行されたデータも 図 2 の様に改行されずに表示される 此れは 新規メール作成ウィンドウを起動する場合 総ての文字が其の儘使用出来るとは限らないからで有る 其の儘使用出来ない文字は 文字コード表示に置き換えて使用する必要が有る 例えば 本文等で使用する 改行 は %0D%0A と謂う文字コード表示に置き換える 図 1 の様に改行されたデータを其の儘新規メール作成ウィンドウに表示する場合 Dim strbody As String strbody = textbox1.text を下記のコードに変更する Dim txtlines( ) As String Dim n As Integer txtlines = TextBox1.Lines For n = 0 To txtlines.getupperbound(0) strbody = strbody & txtlines(n) & "%0D%0A" Next リスト 2 リスト 2 を実装し 図 1 の メーラーの起動 ボタンをクリックすると 図 3 の様に表示される 図 3-18-