プッシュスイッチを押すとメールを送信する

[Arduinoで遊ぶ]

作成 : 2013/01/14

"サーバの実験室"の検索


プッシュスイッチを押すとメールを送信する

Arduino UnoとEthernet Shieldを組み合わせてSMTPクライアントにします。 デジタルピン#7にプッシュスイッチを接続し、ボタンを押した時にメールを送信します。 サーバからのレスポンスを読み取っていますが、解析する処理は省略しています。

接続先は、自宅にあるSMTPサーバ(192.168.1.10)です。 ISP等外部のSMTPサーバを指定するのは、予期しない動作をしたときにご迷惑なので避けました。

SMTPクライアント接続図

/*********************
デジタルピン#7に接続されたプッシュスイッチをオンにしたとき、SMTPサーバに接続してメールを送信する。

  Arduino Uno
    http://www.arduino.cc/en/Main/arduinoBoardUno
  Arduino Ethernet Shield
    http://arduino.cc/en/Main/ArduinoEthernetShield
**********************/

#include <SPI.h>
#include <Ethernet.h>

// Arduino Ethernet ShieldのMACアドレス
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x99, 0x50 };
// Arduinoに設定するTCP/IP情報
byte ip[] = { 192, 168, 1, 200 };
byte gateway[] = { 192, 168, 1, 1 };
byte subnet[] = { 255, 255, 255, 0 };

// 接続するサーバのIPアドレス
IPAddress server(192, 168, 1, 10);

EthernetClient client;

// プッシュスイッチを接続するポートを定義
#define inPin 7
// サーバからの受信するレスポンスの最大文字数を定義
#define MSGBUF 1024



// 最初に1回だけ実行
void setup() {

  // デジタルピン#7を入力に設定
  pinMode(inPin, INPUT);

  // シリアル通信の転送レートを設定
  Serial.begin(9600);

  // ネットワーク設定を初期化
  Ethernet.begin(mac, ip, gateway, subnet);

}



// 繰り返し実行
void loop() {

  // サーバから受信したレスポンスを格納する変数
  char rcvMsg[MSGBUF];

  Serial.println(digitalRead(inPin));
  // デジタルピン#7が'HIGH'だったら
  if (digitalRead(inPin) == HIGH) {

    // SMTPサーバに接続
    client.connect(server, 25);
    Serial.println("connect server");

    // SMTPサーバに接続したらtrue
    if (client.connected()) {
      // 以下、sendCmd関数を呼んでサーバにコマンドを発行し、レスポンスをrcvMsgに格納
      // 最初のコマンドが""なのは、サーバに接続したときのレスポンスを読み取るため
      sendCmd ("", rcvMsg);
      sendCmd ("EHLO nina.jp", rcvMsg);
      sendCmd ("MAIL FROM:foo@nina.jp", rcvMsg);
      sendCmd ("RCPT TO:bar@nina.jp", rcvMsg);
      sendCmd ("DATA", rcvMsg);
      sendCmd ("Subject: TEST MAIL\r\ntest mail\r\n.", rcvMsg);
      sendCmd ("QUIT", rcvMsg);

      delay(1);
      // サーバから切断
      client.stop();
      Serial.println("disconnect server");
    }
  }

  // 1秒待つ
  delay(1000);
}



// サーバにコマンドを発行して、レスポンスを受信する
// 戻り値はレスポンスの文字長
// char* sendStr : サーバに発行するコマンドを格納、char* rcvStr サーバからのレスポンスを格納
long sendCmd(char* sendStr, char* rcvStr) {

  long idx=0;

  // サーバに発行するコマンドがあるときは、サーバにコマンドを送信
  // 発行するコマンドがないとき、サーバからのレスポンス(バナーとかプロンプトとか)があれば受信
  if(sendStr != "") {
    client.println(sendStr);
  }

  Serial.print("send command: "); Serial.println(sendStr);

  // コマンド送信して、レスポンスを受信するまでの時間を調整
  // delayをいれないと、次のclient.available()がfalseになってしまったのです
  delay(10);

  // サーバから受信するレスポンスがある間はtrue
  while (client.available()) {
    // サーバからのレスポンスを読み取る
    char c = client.read();

    // レスポンスをrcvStrに格納する
    // レスポンスが規定最大サイズMSGBUF-1(-1は'\0'付加を考慮した分)を超える場合は、データを破棄
    if (idx < MSGBUF - 1) {
      rcvStr[idx] = c;
      idx++;
    }
  }

  // rcvStrに格納した文字列の後ろにNULLを追加して、文字列の終わりを示す
  rcvStr[idx] = '\0';

  Serial.print("receive message: "); Serial.println(rcvStr);

  // 関数の戻り値として、レスポンスの文字長を返す
  return strlen(rcvStr);
}

シリアル出力結果は以下のようになりました。

0
0
0
1
connect server
send command: 
receive message: 220 linux.nina.jp ESMTP Sendmail 8.14.5/8.14.4; Mon, 14 Jan 2013 15:54:24 +0900

send command: EHLO nina.jp
receive message: 250-linux.nina.jp Hello [192.168.1.200], pleased to meet you
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-8BITMIME
250-SIZE
250-DSN
250-ETRN
250-AUTH DIGEST-MD5 CRAM-MD5
250-STARTTLS
250-DELIVERBY
250 HELP

send command: MAIL FROM:foo@nina.jp
receive message: 250 2.1.0 foo@nina.jp... Sender ok

send command: RCPT TO:bar@nina.jp
receive message: 250 2.1.5 bar@nina.jp... Recipient ok

send command: DATA
receive message: 354 Enter mail, end with "." on a line by itself

send command: Subject: TEST MAIL
test mail
.
receive message: 250 2.0.0 r0E6sO9P002591 Message accepted for delivery

send command: QUIT
receive message: 221 2.0.0 linux.nina.jp closing connection

disconnect server
0
0
0

[Arduinoで遊ぶ]