Visual Basic Tips

2003.02.11 更新

Visual BasicやVBAならBASP21コンポーネントを使わなくてもメール送受信や 正規表現処理が簡単にできます。 BSMTP DLLやBREGEXP DLLを直接Visual Basicから呼出せばいいのです。
Excelでのメール送信サンプルは、 http://homepage1.nifty.com/gak/MSTips/multimail.htmを どうぞ。






メールを送信する

SendMail関数を呼んでメールを送信するサンプルです。 BSMTP.DLLをWindowsのsystemディレクトリかVBアプリケーションを 置くディレクトリにコピーします。
Option Explicit
Private Declare Function SendMail Lib "bsmtp" _
      (szServer As String, szTo As String, szFrom As String, _
      szSubject As String, szBody As String, szFile As String) As String

Private Declare Function FlushMail Lib "bsmtp" _  2003/02/11 New !
      (szServer As String, szDir As String, szLogfile As String) As Long

Private Sub Form_Load()
Dim ret As String
Dim szServer As String, szTo As String, szFrom As String
Dim szSubject As String, szBody As String, szFile As String

szServer = "your smtp"   ' SMTPサーバ名。
                         'タブで区切ってポート番号を指定できます。
szTo = "who@who.com"     ' 宛先
' 複数の宛先に送付するときは、アドレスをタブで区切って
' いくらでも指定できます。
szTo = "who1@who1.com" & vbTab & "who2@who2.com" ' 複数宛先
' CCを指定するには次のようにします。
szTo = "who@who.com" & vbTab & "cc" & vbTab & "who2@who2.com" & _
       vbTab & "who3@who3.com"
' BCCを指定するには次のようにします。
szTo = "who@who.com" & vbTab & "bcc" & vbTab & "who2@who2.com" & _
       vbTab & "who3@who3.com"
' ヘッダを指定するには次のようにタブで区切り、>をヘッダの前に
' つけます。
szTo = "who@who.com" & vbTab & ">Message-ID: 12345"
szFrom = "my@my.com"     ' 送信元
szSubject = "はじめまして"     ' 件名
' 本文内で改行するには、vbCrLfを使います。
szBody = "こんにちは。" & vbCrLf & "さようなら"   ' 本文
' ファイルを添付するときは、ファイル名をフルパスで指定します。
' ファイルを複数指定するときは、タブで区切ってください。
szFile = "c:\a1.gif" & vbTab & "c:\a2.jpeg" ' ファイル2個
' ファイルを添付しないときは次のようにします。
szFile = ""   ' ファイル添付なし

ret = SendMail(szServer, szTo, szFrom, szSubject, szBody, szFile)

' 送信エラーのときは、戻り値にエラーメッセージが返ります。
If Len(ret) <> 0 Then
   msgbox "エラー" & ret
End If

' メールキューにメールファイルを作成2003/02/11 New !
Dim mdir As String, szLogfile As String
Dim rcnt As Long
mdir= "c:\temp\mdir"  ' メールファイルを作成するフォルダ(メールキュー)

rcnt = SendMail(mdir, szTo, szFrom, szSubject, szBody, szFile)

' rcnt にはメールキュー内のメールファイル数が返ります。
'
szLogfile = "c:\temp\log.txt"   ' ログファイル名

rcnt = FlushMail(szServer, szTo, mdir, szLogfile)

' rcnt には送信OKのメール数が返ります。

End Sub

SMTPサーバ名って何でしょう

サーバ名とはSMTPプロトコルをサポートしたメールサーバソフトが 動作しているマシン名です。インターネットメールサーバ名ともいいます。 Outlookなどのメールソフトでインターネットメールの設定プロパティの [メールボックス情報]-[インターネットメールサーバー]に指定する名前です。 次に名前が正しいかどうか確認する方法を説明します。
メール送信するPCでコマンドプロンプトに入ります。
telnet コマンドをSMTPサーバ名とポート番号25で実行します。
> telnet server 25
これで次のような応答が返ってくれば正しいサーバ名です。
220 xxxxxxxxxxxxxxxxxx ESMTP Sendmail 8.8.7/xxxxx ready at Sat, 29 Nov 1997
10:21:26 +0900

SMTPコネクションを切断するには quit コマンドを打ちます。
> quit


SendMail関数が遅いんです

SendMail関数を呼出すとメールサーバにメールデータを送信し終わるまで待ちます。
次に紹介するSendMailEx関数を使えばすぐに処理が戻ります。 SendMailEx関数は、メール送信処理を別プロセス(Bsendm.exe)に任せて さっさと終了します。 SendMailEx関数を使うにはBsendm.exeをWindowsのsystemディレクトリにコピーしておく 必要があります。
Option Explicit
Private Declare Function SendMailEx Lib "bsmtp" _
      (szLogfile As String, szServer As String, szTo As String, _
       szFrom As String, szSubject As String, szBody As String, szFile As String) As String

Private Sub Form_Load()
Dim ret As String
Dim szLogfile As String
Dim szServer As String, szTo As String, szFrom As String
Dim szSubject As String, szBody As String, szFile As String

' メール送信結果を記録するファイル名を指定します。
szLogfile = "c:\log.txt" 
szServer = "your smtp"   ' SMTPサーバ名
                         'タブで区切ってポート番号を指定できます。
szTo = "who@who.com"     ' 宛先
szFrom = "my@my.com"     ' 送信元
szSubject = "はじめまして"     ' 件名
szBody = "こんにちは。" & vbCrLf & "さようなら"   ' 本文
szFile = "c:\a1.gif" & vbTab & "c:\a2.jpeg" ' ファイル2個

ret = SendMailEx(szLogfile,szServer, szTo, szFrom, szSubject, szBody, szFile)

' パラメータエラーのときは、戻り値にエラーメッセージが返ります。
If Len(ret) <> 0 Then
   msgbox "エラー" & ret
End If

End Sub

メールを受信したい

メールを受信するにはRcvMail関数を使います。RcvMail関数でメールボックスからメールを 取出してみましょう。
Option Explicit
Private Declare Function RcvMail Lib "bsmtp" _
      (szServer As String, szUser As String, szPass As String, _
      szCommand As String, szDir As String) As Variant

Private Sub Form_Load()
Dim szServer As String, szUser As String, szPass As String
Dim szCommand As String, szDir As String
Dim ar As Variant, v As Variant

szServer = "your pop3 server"  'SMTPサーバ名と同じでよい。
                               'タブで区切ってポート番号を指定できます。
szUser = "your-name"  'メールアカウント名
szPass = "pass"       'パスワード
      2000/05/20 APOPをサポート
      APOP 認証をするには、パスワードの前に "a" または "A" に 1個の
      ブランクをつけます。
      "a xxxx" : サーバがAPOP 未対応なら通常のUSER/PASS 処理をします。
      "A xxxx" : サーバがAPOP 未対応ならエラーになります。
szCommand = "SAVE 1-3"  'コマンド メールの1件目から3件目までを受信
szDir = "c:\maildata" '受信したメールを保存するディレクトリ

ar = RcvMail(szServer, szUser, szPass, szCommand, szDir)

'戻り値が返る変数は、Variantタイプを指定すること。
'受信したメール1通ごとにファイルが作成されます。
'メールに添付されたファイルは、本文と共に1つのファイルに含まれます。
'ReadMail関数で添付ファイルを取出します。
If IsArray(ar) Then   '正常終了時のSAVEコマンドの戻り値は、配列になります。 
   For Each v In ar
    Debug.Print v     'メールデータが保存されたファイル名がフルパスで戻ります。 
                      'このファイル名をReadMailのパラメータとして渡します。 
   Next
Else
  Debug.Print ar      'エラー発生時は、配列でなくメッセージが戻ります。
End If

End Sub

コマンドは、次のように指定します。
 STAT ...... メールボックスに到着しているメール数と総バイト数のみを返します
 LIST [n[-n2]] ...... メールのSubject、From、Dateヘッダーの内容のみを
             返します。範囲も指定できます。
 SAVE n[-n2] .... n番目のメールを受信します。範囲も指定できます。
 SAVD n[-n2] .... n番目のメールを受信し、サーバのメールボックスから
             削除します。範囲も指定できます。
 SAVEALL ... 全てのメールを受信します
 SAVEALLD .. 全てのメールを受信し、サーバのメールボックスから
             削除します
 DELE n[-n2] .... n番目のメールをメールボックスから削除します。
       範囲も指定できます。

RcvMail関数の戻り値は、Variantタイプで指定します。正常に処理が終了したとき
配列で値が返されます。エラーが発生した場合は、配列を返しません。
配列内容はコマンドによって次のようになります。
 STAT - メール数と総バイト数。例:output(0) -> 2 4011
 LIST - タブで区切られたSubject、From、Dateヘッダーの内容
 例:output(0) -> こんにちは\txxxx@xxxx.xxx\t1998/09/15 11:11:30
     output(1) -> こんにちは2\txxxx@xxxx.xxx\t1998/09/15 12:11:30
 SAVE/SAVED/SAVEALL/SAVEALLD - 受信したメールを保存したファイル名。
  DELE - メッセージが返ります。
 例:"3 message(s) deleted"

メールが保存されるファイルの内容は、RFC822タイプの形式です。
添付ファイルも同じファイルに含まれています。
このRFC822タイプのファイルを読んでヘッダーや本文、添付ファイルを取出したりするには
次に説明するReadMail関数を使います。

メールの受信状態を知りたい

メールを受信状態を知るにはRcvMail2関数を使います。RcvMail2関数でコールバック関数を 指定すると受信中のメールごとに受信バイト数が通知されます。 コールバック関数でメールの受信処理をキャンセルすることもできます。
Option Explicit
Private Declare Function RcvMail2 Lib "bsmtp" _
      (szServer As String, szUser As String, szPass As String, _
      szCommand As String, szDir As String, callback As Long) As Variant

Private Sub Form_Load()
Dim szServer As String, szUser As String, szPass As String
Dim szCommand As String, szDir As String
Dim ar As Variant, v As Variant

szServer = "your pop3 server"  'SMTPサーバ名と同じでよい。
szUser = "your-name"  'メールアカウント名
szPass = "pass"       'パスワード
szCommand = "SAVE 1-3"  'コマンド メールの1件目から3件目までを受信
szDir = "c:\maildata" '受信したメールを保存するディレクトリ

ar = RcvMail2(szServer, szUser, szPass, szCommand, szDir, AddressOf RcvMailCallBack)

End Sub

' コールバック関数は、モジュールに配置すること
Public Function RcvMailCallBack(ByVal item As Long, ByVal totlen As Long) As Long
    Debug.Print item     ' 受信数
    Debug.Print totlen   ' 受信バイト数
    RcvMailCallBack = 0  ' キャンセルするとき 戻り値に 1 を指定
End Function

パラメータや戻り値は、RcvMail関数と同じです。
コールバック関数が有効になるのは、次のSAVE 系のコマンドのみです。
 SAVE n[-n2] .... n番目のメールを受信します。範囲も指定できます。
 SAVD n[-n2] .... n番目のメールを受信し、サーバのメールボックスから
             削除します。範囲も指定できます。
 SAVEALL ... 全てのメールを受信します
 SAVEALLD .. 全てのメールを受信し、サーバのメールボックスから
             削除します

その他の LIST コマンドなどでは、コールバック関数の呼出しは行いません。

ReadMail関数を使ってメールの内容を読む

RcvMail関数でメールボックスから取出したメールを読むには、ReadMail関数を使います。
Option Explicit
Private Declare Function ReadMail Lib "bsmtp" _
      (szFilename As String, szPara As String, szDir As String) As Variant

Private Sub Form_Load()
Dim szFilename As String, szPara As String, szDir As String
Dim retv As Variant, v As Variant

szFilename = ar(0)  ' ファイル名にはRcvMailの戻り値の配列からファイル名を設定
szDir = "c:\mail"   ' 添付ファイルが保存されるディレクトリ
szPara = "subject:from:date:"  ' ヘッダーの指定
                               ' nofile: とすると添付ファイルを保存しません。

retv = ReadMail(szFilename,szPara,szDir)

If IsArray(retv) Then
   For Each v In retv
    Debug.Print v
   Next
Else
  Debug.Print retv
End If
End SUb

ReadMail関数は、読込んだメールの内容を配列で返します。
入力となるファイル名は、RcvMailで作成されたファイルを指定します。
ヘッダー、本文、添付ファイル名の順番に設定されます。
エラーが発生した場合は、配列を返しません。
例:output(0) -> To: xxxx@xxxx.xxx
    output(1) -> From: who@who.com
    output(2) -> Date: 1998/09/15 12:30:31
    output(3) -> .....
    output(4) -> Body: 本文
    output(5) -> File: ファイル名1
    output(6) -> File: ファイル名2

SortMail関数を使ってメールの内容をソート

SortMail関数を使えば RcvMail関数で保存したメールをソートしたり選択したりできます。
Option Explicit
Private Declare Function SortMail Lib "bsmtp" _
      (szDir As String, szHeader As String, opt As Long, _
       szFilter As String,delflag As Long) As Variant

Private Sub Form_Load()
Dim szDir As String, szHeader As String, opt As Long
Dim szFilter As String, delflag As Long
Dim retv As Variant, v As Variant

szDir = "c:\mail"   ' メールファイルのディレクトリ
szFilter = "date:"  ' ソートヘッダーの指定
opt = 1             ' 逆順ソート
szFilter = "from:=babaq" ' 送信元が babaq 
delflag = 0         ' 削除しない

retv = SortMail(szDir,szHeader,opt,szFilter,delflag)

If IsArray(retv) Then
   For Each v In retv
    Debug.Print v
   Next
Else
  Debug.Print retv
End If
End Sub

szDir    : メールファイルのディレクトリ名。
szHeader : ソート対象のヘッダ名。ソートしない場合(選択や削除のみ)は、""。
               * で総称名が使えます。
               例:
               "From:"    - 送信元でソート
               "Date:"    - 送信日付でソート
               "Subject:" - 件名でソート
               "X-Mail*"  - X-Mailer または X-Mail-Agent ヘッダでソート。
opt       : ソートオプションを数字で指定。デフォルト値は、0。
               0 - 順ソート
               1 - 逆順ソート
               2 - 大文字小文字無視
szFilter  : 選択オプション。デフォルトは、"" ですべて選択します。
               ヘッダ名 + 条件 + 文字列で指定します。
               ヘッダ名は、*: で総称指定できます。
               文字列は、大文字小文字を無視します。
               文字列を指定しないと、ヘッダが存在するしないで選択できます。
               本文("Body:")や添付ファイル("File:")も指定可能。
               条件: = 後続の文字列を含むものを選択
                      ! 後続の文字列を含まないものを選択
               例:
               "From:=babaq"   - 送信元にbabaq を含むメール
               "To:!hoge"      - 宛先に hoge を含まないメール
               "Body:=babaq"   - 本文に babaq を含むメール
               "References:="  - References ヘッダを含むメール
               "References:!"  - References ヘッダを含まないメール
               "X-Mail*:=outlook"   - Microsoft OutLook で送信したメール
                                      X-Mailer または X-Mail-Agent: ヘッダが該当します。
delflag    : 削除オプション。選択オプションと共に使います。デフォルトは、0。
               0 - 削除しません。
               1 - 選択条件に一致したものを削除します。
outarray   : ソート(あるいは選択、削除)されたファイル名を配列で返します。
                  エラーや該当するメールファイルがないときは配列でなく文字列が返ります。

使用例:
Dim dirx As String, outarray As Variant
dirx = "d:\mail" 
outarray = SortMail(dirx,"date:",1,"",0)  ' 最新日付の順にソート
' 古い日付の順にソート。Fromヘッダに hoge が含まれているメールのみ
outarray = SortMail(dirx,"date:",0,"from:==hoge",0)
' Fromヘッダに hoge が含まれているメールのみ削除
outarray = SortMail(dirx,"",0,"from:==hoge",1)
' 添付ファイルがあるメールのみ削除
outarray = SortMail(dirx,"",0,"File:=",1)
' Beckyで送信されたメールのみ取出す
outarray = SortMail(dirx,"",0,"X-Mailer:=becky",0)


正規表現を使ってみたい

正規表現は、文字列をパターンとして処理することができます。 ここではBREGEXP DLLが提供するMatch/MatchEx/Replace/Translate/Split関数を紹介します。 はじめに、BREGEXP.DLLをWindowsのsystemディレクトリかVBアプリケーションを 置くディレクトリにコピーします。
Private Declare Function Match Lib "bregexp" _
      (szRegstr As String, szTarget As String) As String

Private Declare Function MatchEx Lib "bregexp" _
      (szRegstr As String, szTarget As String, mode As Long) As Variant

Private Declare Function Replace Lib "bregexp" _
      (szRegstr As String, szTarget As String) As String

Private Declare Function Translate Lib "bregexp" _
      (szRegstr As String, szTarget As String, ret As String) As Long

Private Declare Function Split Lib "bregexp" _
      (szRegstr As String, szTarget As String, limit As Long) As Variant



'◆Match
' Match関数は、パターンマッチで文字列検索を行ない、"1" または偽 ("0") を返します。
' グループメタ文字"()"を使った場合は、マッチした文字列を返します。
' szRegstr : パターン。
' szTarget : 対象文字列。
' 戻り値   : "1"または"0"またはマッチした文字列。
' パターンは、次のように指定します。パターンの詳細は、Perlのマニュアルを参照。
'  /PATTERN/gik
'       g   グローバルにマッチ、つまり、すべてを探し出す
'       i   大文字、小文字を区別しない
'       k   日本語を処理する。日本語をシングル文字として処理しない。
'       m   文字列を複数行として扱う。
'
ret = Match("/\d{3}/", szTarget)
If ret then
  '数字が3桁含まれている
End If
' 連続している3桁の数字を取出す
ret = Match("m/(\d{3})/", szTarget)
'
'
'◆MatchEx
' MatchEx関数は、パターンマッチの拡張版です。正規表現メモリ(Perl の $1 $2 に対応)や
' すべてのマッチ文字を' を返します。グループメタ文字"()"は、マッチした文字を記憶します。
' szRegstr : パターン。
' szTarget : 対象文字列。
' mode     : マッチモードを数字で指定します。
'            0 : 正規表現メモリモード
'            1 : すべてのマッチ文字を返します
' 戻り値   : マッチ結果を配列で返します。
'          正規表現メモリモード:
'          out(0) : マッチした文字列そのもの。Perl では $& 。
'          out(1) : マッチ文字列の前の文字列。Perl では $` 。 
'          out(2) : マッチ文字列の後の文字列。Perl では $' 。
'          out(3) : メモリ1の文字列。Perl では $1 。
'          out(4) : メモリ2の文字列。Perl では $2 。
'          out(n) : メモリnの文字列。Perl では $n 。
'          すべてのマッチ:
'          out(0) : マッチした文字列1。
'          out(1) : マッチした文字列2。
'          out(2) : マッチした文字列3。
'          out(n) : マッチした文字列n。
'
'
ret = MatchEx("/\d{3}/", szTarget,1)  ' すべての3桁の数字を求める
If IsArray(ret) then   ' 配列のとき、マッチ
   Dim v As Variant
   For Each v In ret
    Debug.Print v
   Next
End If
'
'
'◆Replace
' Replace関数は、文字列中でパターンを検索し、もし見つかれば、置換テキストで置き換えた
' 文字列を返します。
' szRegstr : パターン。
' szTarget : 対象文字列。
' 戻り値   : 置換後の文字。
' パターンは、次のように指定します。パターンの詳細は、Perlのマニュアルを参照。
'   s/PATTERN/REPLACEMENT/gikm
'
' 数字をすべてxに変更する例。
ret = Replace("s/\d/x/g", szTarget)
'
' Perlのマニュアルに出てた最初の 2 語を入替える例。なんの意味があるのでしょうか(笑)
ret = Replace("s/^([^ ]*) *([^ ]*)/$2 $1/",szTarget)
'
'
'◆Translate
' Translate関数は、検索リスト (SEARCHLIST) に含まれる文字を、対応する置換リスト
' (REPLACEMENTLIST) の文字に変換します。また、置換または削除が行なわれた、文字数を返します。
' szRegstr : パターン。
' szTarget : 対象文字列。
' ret      : 置換後の文字列。
' 戻り値   : 文字数。
' パターンは、次のように指定します。パターンの詳細は、Perlのマニュアルを参照。
'     tr/SEARCHLIST/REPLACEMENTLIST/cds
'
'        オプションには、
'          c   SEARCHLIST を補集合にする
'          d   見つかったが置換されなかった文字を削除する
'          s   置換された文字が重なったときに圧縮する
'          k   日本語を処理する。日本語をシングル文字として処理しない。
'
' 小文字を大文字に変更する例。
Dim ctr as Long
ctr = Translate("tr/a-z/A-Z/", szTarget, ret)
'
'
'◆Split
' Split関数は   文字列を文字列の配列に分割して、それを返します。
' szRegstr : パターン。Match関数と同じ。
' szTarget : 対象文字列。
' limit    : 配列数の制限値。0を指定すると無制限。
' 戻り値   : 配列。
Dim retv as Variant,v as Variant
retv = Split("/\d/k", "5,4,6,c", 30)
If IsArray(retv) Then
   For Each v In retv
    
    Debug.Print v
   Next
Else
  Debug.Print retv
End If



プログラムコードのご使用上の注意

●プログラムコードを使って発生した損害に関しては、一切の責任を負いません。
●使用、配布に制限はありません。自由にお使いください。
●動作の保証はありません。
●動作を確認したOSは、Windows NT 4.0 とWindows 95/98/Me/XP/2000のみです。

Home


Copyright 1999-2003 Tatsuo Baba,All rights reserved.