Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Maik Schmidt - Arduino A Quick-Start Guide, 2nd Edition (The Pragmatic Programmers) - 2015.pdf
Скачиваний:
146
Добавлен:
22.03.2016
Размер:
30.47 Mб
Скачать

Emailing Directly from an Arduino 189

Emailing Directly from an Arduino

To send an email from the Arduino, we’ll basically implement the telnet session from the previous chapter. Instead of hardwiring the email’s attributes into the networking code, we’ll create create something more advanced.

We start with an Email class:

Ethernet/Email/email.h

#ifndef __EMAIL__H_ #define __EMAIL__H_

class Email {

String _from, _to, _subject, _body;

public:

Email(

const String& from, const String& to, const String& subject, const String& body

) : _from(from), _to(to), _subject(subject), _body(body) {}

const String& getFrom()

const { return

_from; }

const String& getTo()

const { return

_to; }

const String&

getSubject()

const

{ return

_subject; }

const String&

getBody()

const

{ return

_body; }

};

#endif

This class encapsulates an email’s four most important attributes—the email addresses of the sender and the recipient, a subject, and a message body. We store all attributes as String objects.

Wait a minute…a String class? Yes! The Arduino IDE comes with a full-blown string class.4 It doesn’t have as many features as the C++ or Java string classes, but it’s still way better than messing around with char pointers. You’ll see how to use it in a few paragraphs.

The rest of our Email class is pretty straightforward. In the constructor, we initialize all instance variables, and we have methods for getting every single attribute. We now need an SmtpService class for sending Email objects:

4.http://arduino.cc/en/Reference/StringObject

report erratum • discuss

Chapter 11. Creating a Burglar Alarm with Email Notification 190

 

Ethernet/Email/smtp_service.h

Line 1

#ifndef __SMTP_SERVICE__H_

-

#define __SMTP_SERVICE__H_

-

 

 

-

#include "email.h"

5

 

 

-

class SmtpService {

-

boolean

_use_auth;

-

IPAddress

_smtp_server;

-unsigned int _port;

10

String

_username;

-

String

_password;

-

 

 

-void read_response(EthernetClient& client) {

-delay(4000);

15 while (client.available()) {

-const char c = client.read();

-Serial.print(c);

-}

-}

20

-void send_line(EthernetClient& client, String line) {

-const unsigned int MAX_LINE = 256;

-char buffer[MAX_LINE];

-line.toCharArray(buffer, MAX_LINE);

25 Serial.println(buffer);

-client.println(buffer);

-read_response(client);

-}

-

30 public:

-

-SmtpService(

-

const IPAddress&

smtp_server,

-const unsigned int port) : _use_auth(false),

35

_smtp_server(smtp_server),

-

_port(port) { }

-

 

-SmtpService(

-

const IPAddress&

smtp_server,

40

const unsigned int

port,

-

const String&

username,

-

const String&

password) : _use_auth(true),

-

 

_smtp_server(smtp_server),

-

 

_port(port),

45

 

_username(username),

-

 

_password(password) { }

-

 

 

-void send_email(const Email& email) {

-EthernetClient client;

report erratum • discuss

Emailing Directly from an Arduino 191

50

Serial.print("Connecting...");

-

 

-if (client.connect(_smtp_server, _port) <= 0) {

-Serial.println("connection failed.");

-} else {

55 Serial.println("connected.");

-read_response(client);

-if (!_use_auth) {

-Serial.println("Using no authentication.");

-send_line(client, "helo");

60 }

-else {

-Serial.println("Using authentication.");

-send_line(client, "ehlo");

-send_line(client, "auth login");

65 send_line(client, _username);

-send_line(client, _password);

-}

-send_line(

-client,

70 "mail from: <" + email.getFrom() + ">"

-);

-send_line(

-client,

-"rcpt to: <" + email.getTo() + ">"

75 );

-send_line(client, "data");

-send_line(client, "from: " + email.getFrom());

-send_line(client, "to: " + email.getTo());

-send_line(client, "subject: " + email.getSubject()); 80 send_line(client, "");

-send_line(client, email.getBody());

-send_line(client, ".");

-send_line(client, "quit");

-client.println("Disconnecting.");

85 client.stop();

-}

-}

-};

-

90 #endif

Admittedly, this is a lot of code, but we’ll walk through it step by step. First, the SmtpService class encapsulates the SMTP server’s IP address and its port. These attributes are required in any case. In addition, we store a username and a password in case someone’s going to use an authenticated connection.

To communicate with an SMTP server, we have to read its responses, and we do that using the private read_response method starting on line 13. It waits for

report erratum • discuss

Chapter 11. Creating a Burglar Alarm with Email Notification 192

four seconds (SMTP servers usually are very busy, because they have to send a lot of spam), and then it reads all the data sent back by the server and outputs it to the serial port for debugging purposes.

Before we can process responses, we have to send requests. send_line, beginning in line 21, sends a single command to an SMTP server. You have to pass the connection to the server as an EthernetClient instance, and the line you’d like to send has to be a String object.

To send the data stored in a String object, we need to access the character data it refers to. We can use toCharArray or getBytes to retrieve this information. These two methods do not return a pointer to the string’s internal buffer. Instead, they expect you to provide a sufficiently large char array and its size. That’s why we copy line’s content to buffer before we output it to the serial and Ethernet ports. After we’ve sent the data, we read the server’s response and print it to the serial port.

There aren’t any surprised in the public interface. There are two constructors. The first, on line 32, expects the SMTP server’s IP address and its port. If you use it, the SmtpService class assumes you’re not using authentication.

To authenticate against the SMTP service using a username and a password, you have to use the second constructor, starting in line 38. In addition to the SMTP server’s IP address and port, it expects the username and password encoded in Base64.

The send_email method is the largest piece of code in our class, but it’s also one of the simplest. It mimics exactly our telnet session. The only thing worth mentioning is line 57. Here we check whether authentication information has been provided in the constructor. If not, we send the HELO command. If authentication information has been provided, we send the EHLO command and the corresponding authentication information.

Let’s use our classes now to actually send an email:

Ethernet/Email/Email.ino

Line 1 #include <SPI.h>

-#include <Ethernet.h>

-#include "smtp_service.h"

-

5

const unsigned int SMTP_PORT

= 2525;

-

const unsigned int BAUD_RATE

= 9600;

-

const String

USERNAME

= "bm90bXl1c2VybmFtZQ=="; // Encoded in Base64.

-

const String

PASSWORD

= "bm90bXlwYXNzd29yZA=="; // Encoded in Base64.

-

 

 

 

10

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

-

IPAddress my_ip(192, 168, 2,

120);

report erratum • discuss

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]