} else { // if it doesn't match, it's not safe to continue
Serial.println("Certificate doesn't match");
return -1;
}
Serial.print("Requesting URL: ");
Serial.println(url);
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Authorization: Basic " + credentials + "\r\n" +
"User-Agent: ESP8266\r\n" +
"Connection: close\r\n\r\n"); // Send the HTTP request headers
Serial.println("Request sent");
int unread = -1;
while (client.connected()) { // Wait for the response. The response is in XML format
client.readStringUntil('<'); // read until the first XML tag
String tagname = client.readStringUntil('>'); // read until the end of this tag to get the tag name
if (tagname == "fullcount") { // if the tag is <fullcount>, the next string will be the number of unread
emails
String unreadStr = client.readStringUntil('<'); // read until the closing tag (</fullcount>)
unread = unreadStr.toInt(); // convert from String to int
break; // stop reading
} // if the tag is not <fullcount>, repeat and read the next tag
}
Serial.println("Connection closed");
return unread; // Return the number of unread emails
}
How it works
The setup should be pretty familiar by now.
The only new thing is the getUnread() function:
First, it starts an HTTPS connection to the Gmail server on port 443. Then it checks if the fingerprint of the certificate matches, so it
knows that it's the real Google server, and not some hacker. If the certificate doesn't match, it's not safe to send the credentials to the
server.
If it matches, we send a HTTP GET request to the server:
GET /mail/feed/atom HTTP/1.1\r\n
Host: mail.google.com\r\n
Authorization: Basic aVeryLongStringOfBase64EncodedCharacters=\r\n
User-Agent: ESP8266\r\n
Connection: close\r\n\r\n
The request contains the URI we want to access (in this case this is the Atom feed URL), the host (which is mail.google.com), and the
base64-encoded version of your login credentials.
As you can see, the different lines of the header are separated by a CRLF (Carriage Return + Line Feed, \r\n). Two CRLF's mark the end
of the header.
The Gmail server will process our request, and send the feed as a response over the same HTTPS connection. This response is an XML
document, that consists of tags with angled brackets, just like HTML. If you need a lot of data, it's recommended to use a proper XML
parser library, but we only need one tag, so we can just skim through the response text until we find the <fullcount>x</fullcount>
tag. The number inside this tag is the number of unread emails in the inbox.
We can just convert it to an integer, and stop reading.
This is the format of the XML feed, you can see the fullcount tag on line 5:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://purl.org/atom/ns#" version="0.3">
<title>Gmail - Inbox for esp8266.test.mail@gmail.com</title>
<tagline>New messages in your Gmail Inbox</tagline>
<fullcount>5</fullcount>
<link rel="alternate" href="https://mail.google.com/mail" type="text/html" />
<modified>2017-03-05T15:54:06Z</modified>
<entry>
<title>New sign-in from Firefox on Linux</title>
<summary>New sign-in from Firefox on Linux Hi ESP8266, Your Google Account esp8266.test.mail@gmail.com was just used to sign in
from Firefox on Linux. ESP8266 Test esp8266.test.mail@gmail.com Linux Sunday,</summary>
<link rel="alternate" href="https://mail.google.com/mail?
account_id=esp8266.test.mail@gmail.com&message_id=123456789&view=conv&extsrc=atom" type="text/html" />
<modified>2017-03-05T15:52:45Z</modified>
<issued>2017-03-05T15:52:45Z</issued>
<id>tag:gmail.google.com,2004:123456789123456789</id>
<author>
<name>Google</name>
<email>no-reply@accounts.google.com</email>
</author>
</entry>
...
</feed>
The loop just prints the number of unread emails, and turns on an LED if you have unread messages.
Getting the fingerprint of the Gmail server
Like I mentioned before, we need a fingerprint to check the identity of the server. To get this fingerprint, execute the following
command in a terminal (Linux & Mac):
openssl s_client -connect mail.google.com:443 < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin | sed 's/:/ /g'
Copy the hexadecimal fingerprint string and paste it into the sketch on line 12. For example:
const char* fingerprint = "D3 90 FC 82 07 E6 0D C2 CE F9 9D 79 7F EC F6 E6 3E CB 8B B3";
Need help?
Do you have a question about the ESP8266 and is the answer not in the manual?
Questions and answers