Home > 日常 > キャプチャー画像をファイルに保存せずメール送信する

キャプチャー画像をファイルに保存せずメール送信する

  • 2008-10-15 (水) 13:02
  • 日常
  • 投稿者:hitotsu
[開発環境]
WindowsXP Professional SP3,
Intel Xeon2.13GHz,4GBメモリ,160GB HDD,
Visual Studio 2005 Professional Edition(VB.NET)

「キャプチャー画像はファイルに保存してメール送信する」
これが、よく行われていることだと思います。
わかりやすいし、例題のコードもネットで検索すると、すぐ見つかります。

本題のような要求は、ネット検索すると掲示板などに確かに存在します。
ただ、要求は画像そのものはなく、文書ファイルやExcelファイルです。

掲示板に寄せられる返信は、

・ファイルに保存する方法
・何でメモリに蓄積しておくの?
・MemoryStreamを使う方法(具体的なコードなし)

という内容で、有用性が見出されていないため、ピンと来る解決策が
示されていないように思われます。

ファイルに保存せずにメール送信/Web転送する方法は、MSDNやネットの
情報で、MemoryStreamを利用すればいけそうです。
しかし、実際のコードを目にすることはありませんでした。

そろそろ、お題目について説明します。

Webカメラキャプチャーソフト(WebCameraSnap)では、定期的あるいは
動きの有無を識別した時に、キャプチャー画像を外部に送信します。
(ローカルディスクへの書き出しがメインです)

通常であれば、ファイルに保存する方法で全く問題ないのですが、
次のように、パソコン側の制約、システム運用上の要望がある場合
には、ファイル保存を行わない方法が有用かと考えました。

・ディスク装置の書換回数が限られており、ファイル書き込みをなくしたい
・ハードディスクの容量が極めて限られているため、極力保存したくない
・PCを盗まれた時にキャプチャー画像をファイルとして残したくない

Eee PCなどの小型PCでキャプチャーソフトを動作させようとすることを
想定しています。
運用を始めてからでは遅いので、プログラムが対応可能か実験です。
メモリーとCPUパワーが必要なので、(購入できる予算があって^^;)
使えそうなモデルが登場したら実験したいですね。
スポンサーさん、大歓迎です。

今回の実験では、画像をファイル化せずにメール送信してみました。
Web転送(POST)も同じような要領で実現することができますので、
メール送信のみテストコードを掲載します。

なお、実験にあたりキャプチャーデバイスから画像取り込みのかわりに
Windowsのサンプル画像を読み込んでBitmapデータを生成しています。
ここだけはファイルが必要になりますが、ご容赦ください。
(2008/10/26追記:New Bitmap(width,height)にしてもよかったです)

メール送信パラメータは、ダミーのホスト名やメールアドレスを掲示
しますが、環境に応じて書き換えてください。

メール送信は25番ポートに直接送信していますが、実用上はSMTP認証に
対応してあげた方がよいと思います。

あと、エラー処理も入れていませんので、使われる方で実装してください。

Form1にButton1を配置して以下のようなコードで実験しました。
ファイル読み込み、メール送信などでエラーが発生する場合は、
例外を捕捉して対処してください。

VB.NETプログラムをBlog用に整形するのに、八角研究所さんの
ソースコードHTML変換「唐辛子」」を利用しました。とても使い易い
サービスをご提供いただいて感謝です。

[作成したプログラム]



Imports System.IO ' MemoryStreamクラス利用
Public Class Form1
' bitmapデータをメモリーストリームに保存してメール送信する
' smtp_host,e_to,e_from,e_from_nameは環境に合わせて書き換えてください
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim path As String = "C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures"
Dim arr_fname() As String = { _
System.IO.Path.Combine(path, "Sunset.jpg"), _
System.IO.Path.Combine(path, "Winter.jpg") _
}
Dim arr_bmp(arr_fname.GetUpperBound(0)) As Bitmap
For i As Integer = 0 To arr_bmp.GetUpperBound(0)
arr_bmp(i) = CType(Bitmap.FromFile(arr_fname(i)), Bitmap)
Next
Dim subject As String = "ファイルなしで画像添付メールを送信するテスト"
Dim body As String = "テスト本文"
Dim smtp_host As String = "hogehoge.domain"
Dim e_to As String = "to@hogehoge.domain"
Dim e_from As String = "from@hogehoge.domain"
Dim e_from_name As String = "送信者名"
send_attach_email(arr_bmp, arr_fname, smtp_host, subject, body, e_to, e_from, e_from_name)
For i As Integer = 0 To arr_bmp.GetUpperBound(0)
arr_bmp(i).Dispose()
arr_bmp(i) = Nothing
Next
MessageBox.Show("送信完了しました")
End Sub

' 参考URL http://dobon.net/vb/dotnet/internet/smtpclient.html
Function EncodeMailHeader(ByVal str As String, _
ByVal enc As System.Text.Encoding) As String
'Base64でエンコードする
Dim ret As String = System.Convert.ToBase64String(enc.GetBytes(str))
'RFC2047形式に
ret = String.Format("=?{0}?B?{1}?=", enc.BodyName, ret)
Return ret
End Function

' Bitmap配列画像をファイル名配列のファイル名として添付してメールを送信
' エラー処理はありません
' 画像はjpeg形式とします
' SubjectはBASE64エンコード
' 文字コードはJIS
Function send_attach_email(ByVal arr_bmp() As Bitmap, _
ByVal arr_fname() As String, _
ByVal smtp_host As String, _
ByVal subject As String, _
ByVal body As String, _
ByVal e_to As String, _
ByVal e_from As String, _
ByVal e_from_name As String) As Boolean

Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding(50220) ' JIS
Dim msg As New System.Net.Mail.MailMessage()
msg.From = New System.Net.Mail.MailAddress(e_from, EncodeMailHeader(e_from_name, enc))
msg.To.Add(New System.Net.Mail.MailAddress(e_to, EncodeMailHeader("", enc)))
msg.Subject = EncodeMailHeader(subject, enc)
msg.BodyEncoding = enc
msg.Body = body

' 添付ファイルを追加
Dim attach_sum As Integer = arr_bmp.GetUpperBound(0)
Dim attach_idx As Integer = 0
Dim attach(attach_sum) As System.Net.Mail.Attachment
Dim memStream(attach_sum) As MemoryStream
For i As Integer = 0 To attach.GetUpperBound(0)
memStream(i) = New MemoryStream()
Dim ImageFormat As System.Drawing.Imaging.ImageFormat = Nothing
ImageFormat = System.Drawing.Imaging.ImageFormat.Jpeg
arr_bmp(i).Save(memStream(i), ImageFormat)
memStream(i).Position = 0
Dim fname As String = ""
fname = System.IO.Path.GetFileName(arr_fname(i))
attach(attach_idx) = New System.Net.Mail.Attachment(memStream(i), fname, System.Net.Mime.MediaTypeNames.Image.Jpeg)
msg.Attachments.Add(attach(attach_idx))
attach_idx += 1
Next

' メール送信
Dim sc As New System.Net.Mail.SmtpClient()
sc.Port = 25
sc.Host = smtp_host
sc.Timeout = 30000
sc.Send(msg)

msg.Dispose()

' attachに入っているSystem.Net.Mail.Attachmentインスタンスを破棄
For i As Integer = 0 To attach.GetUpperBound(0)
attach(i).Dispose()
memStream(i).Dispose()
Next
End Function
End Class