π IMAP Overview
If you have ever set up an email client or app, you will have certainly come across the terms POP
and IMAP
.
IMAP-is short for Internet Message Access Protocol
, while POP-translates to Post Office Protocol
. In other words, both are email protocols. You might listen about Outlook
, Thunderbird
, Eudora
, GNUMail
, or (Mac) Mail
app which provides custom mail management services they download messages from your email account and to make changes like archiving messages or sorting them into folders and giving more personalization.
Essentially, the main difference of the two protocols is that POP downloads emails from the server for permanent local storage, while IMAP leaves them on the server and just caches (temporarily stores) emails locally. In other words, IMAP is a form of cloud storage.
π When Choose POP:-
- if you want to access your mail from only one single device.
- if need constant access to your email, regardless of internet availability.
- if you have limited server storage.
π When Choose IMAP:-
- if want to access your email from multiple different devices.
- if you have a reliable and constant internet connection.
- if you want to receive a quick overview of new emails or emails on the server.
- if local storage space is limited.
- if worried about backing your emails up.
If confused, then go with IMAP. Itβs the more modern protocol, it allows you to be flexible, and your email is automatically backed up on the server.
Today, we're going to look into IMAP, It's the open standard that describes how to access messages in an email mailbox. While we want to read and send mail programmatically, then IMAP is important. we just need an IMAP client with implemented on top of IMAP protocol standards.
Now let's deep dive into it. Weβre going to connect to an email account, list all of the available folders in the mailbox, and download a message. Here, we are going to use NodeJS IMAP Client
which will help us to explore,
π Enable IMAP permission for your E-Mail
- Log in your Gmail then, Open Email Setting, then Select
Forwarding and POP/IMAP
tab and change the status toIMAP access: Status: IMAP is enabled
. To do so SelectEnable IMAP
. After login into Gmail, Click Dynamic Link For Quick Access. - Now enable
Less Secure Apps: ON
. To do After login into Gmail, Click Dynamic Link For Quick Access.
π° Now, Setup IMAP Client
Here, I'm using nodejs client but you can use other language clients to achieve those features,
Before creating a node application make sure node is installed in your machine, You can find the installation guide from here [https://nodejs.org/en/download/].
node --version
npm --version
π°Create a node application,
mkdir imap-client-app
npm init -y
npm install --save imap
Note: NodeJs library Node-IMAP Client at Github.
π Take a look at implementation,
π° Now, create manage-mailbox.js
files
const Imap = require('imap'), inspect = require('util').inspect;
let getEmailFromInbox = (mailServer) => {
mailServer.openBox('INBOX', true, function (err, box) {
if (err) throw err;
// we can define range '1:3'
let f = mailServer.seq.fetch('1:*', {
bodies: 'HEADER.FIELDS (FROM TO SUBJECT DATE)',
struct: true
});
f.on('message', function (msg, seqno) {
console.log('Message #%d', seqno);
let prefix = '(#' + seqno + ') ';
msg.on('body', function (stream, info) {
let buffer = '';
stream.on('data', function (chunk) {
buffer += chunk.toString('utf8');
});
stream.once('end', function () {
console.log(prefix + 'Parsed header: %s', inspect(Imap.parseHeader(buffer)));
});
});
});
f.once('error', function (err) {
console.log('Fetch error: ' + err);
});
f.once('end', function () {
console.log('Done fetching all messages!');
//mailServer.end();
});
});
}
let createLabel = (mailServer, labelName) => {
mailServer.addBox(labelName, (err) => {});
console.log('message', 'New Label or Box Created');
}
let getMailboxStatusByName = (mailServer, inboxName) => {
mailServer.status(inboxName, (err, mailbox) => {
console.log('message', mailbox);
});
console.log('message', 'Label or Box Status');
}
let getMailBoxLabels = (mailServer) => {
mailServer.getBoxes((error, mailbox) => {
console.log('message', mailbox);
})
}
let deleteLabel = (mailServer, labelName) => {
mailServer.delBox(labelName, (error) => {})
console.log('message', 'Label or Box removed');
}
let mailServer1 = new Imap({
user: 'example@gmail.com',
password: 'password',
host: 'imap.gmail.com',
port: 993,
tls: true,
tlsOptions: {
rejectUnauthorized: false
},
authTimeout: 3000
}).once('error', function (err) {
console.log('Source Server Error:- ', err);
});
mailServer1.once('ready', function () {
mailServer1.openBox('INBOX', true, function (err, box) {
if (err) throw err;
console.log('message', 'server1 ready');
});
// mail operation
getMailBoxLabels(mailServer1);
getEmailFromInbox(mailServer1)
createLabel(mailServer1, "demo-label1");
deleteLabel(mailServer1, "demo-label1");
getMailboxStatusByName(mailServer1, "INBOX");
})
mailServer1.connect();
π° To run that script, hit below command, see output
node manage-mailbox.js
π° We can import and export email, one email server to another email server. To copy email create copy-mailbox.js
,
const Imap = require('imap'), inspect = require('util').inspect;
// Here, copy email source-mail-server to target-mail-server
let copyEmail = (srcServer1, srcServer2, emailServerName) => {
srcServer1.search(['ALL'], (error, uids) => {
//console.log('message', uids);
var count = uids.length;
var f = srcServer1.fetch(uids, { bodies: 'HEADER.FIELDS (FROM TO SUBJECT DATE)', struct: true });
f.on('message', function (msg, seqno) {
//console.log('Got a message with seq no: ' + seqno);
var buffer = [], bufLen = 0, bufferText = '';
msg.on('body', function (stream, info) {
stream.on('data', function (chunk) {
bufferText += chunk.toString('utf8');
buffer.push(chunk);
bufLen += chunk.length;
});
stream.once('end', function () {
console.log('Parsed header: %s', inspect(Imap.parseHeader(bufferText))); // email contents
console.log(`====${emailServerName} - Finished message no. ${seqno} =======`); // email email seqno
//console.log('message-binay-buffer', buffer);
//console.log('message-bufLen', bufLen);
//console.log('message-total-email-count', count);
buffer = Buffer.concat(buffer, bufLen);
srcServer2.append(buffer, {
date: new Date(msg.date),
flags: ['Seen']
}, function (err) {
if (err) throw err;
if (--count === 0) {
console.log('Done copying!');
srcServer2.end() // close mail server1 connection
srcServer1.end() // close mail server2 connection
}
});
});
});
});
f.once('error', function (err) {
console.log('Fetch error: ' + err);
});
f.once('end', function () {
console.log('Done fetching all messages!');
});
});
};
let srcServer2 = new Imap({
user: 'example-target@gmail.com',
password: 'password',
host: 'imap.gmail.com',
port: 993,
tls: true,
tlsOptions: {
rejectUnauthorized: false
},
authTimeout: 3000
}).once('error', function (err) {
console.log('Target mail server error:- ', err);
});
srcServer2.once('ready', function () {
srcServer2.openBox('INBOX', true, function (err, box) {
if (err) throw err;
console.log('message', 'Target mail server ready');
let srcServer1 = new Imap({
user: 'example-source@gmail.com',
password: 'password',
host: 'imap.gmail.com',
port: 993,
tls: true,
tlsOptions: {
rejectUnauthorized: false
},
authTimeout: 3000
}).once('error', function (err) {
console.log('Source Server Error:- ', err);
});
srcServer1.once('ready', function () {
srcServer1.openBox('INBOX', true, function (err, box) {
if (err) throw err;
console.log('message', 'Source mail server ready');
copyEmail(srcServer1, srcServer2, 'Server1');
})
});
srcServer1.connect();
});
})
srcServer2.connect();
π° To run that script, hit below command, see the output
node copy-mailbox.js
Weβve done it! youβve learned major components of IMAP. We connected to an IMAP server, logged in to our email account, listed folders on the remote server, and downloaded message data, create a label, list of mail count. This is exactly what happens under the hood in email apps as you browse your mailbox.
π Bonus Section
π° Read Unseen email and update flag.
If, we like to parse email, use Mailparser
. which is an advanced email parser for Node.js
. Install package from here [https://nodemailer.com/extras/mailparser/]
npm install mailparser --save
// false = read only mood off, so after fetch we can update flag.
server.openBox('INBOX', false, function (err, box) {
if (err) throw err;
server.search(['UNSEEN'], function (err, results) {
let f = server.fetch(results, {bodies: ''});
const simpleParser = require('mailparser').simpleParser;
f.on('message', function (msg, seqno) {
let uid, headers, body = '';
msg.on('body', function (stream, info) {
simpleParser(stream, (err, parsed) => {
console.log(parsed.text)
console.log(parsed.textAsHtml)
});
});
msg.once('attributes', function (attrs) {
uid = attrs.uid;
console.log(attrs);
});
});
f.once("error", function (err) {
return Promise.reject(err);
});
});
});
π Congratulations. & Thanks for your time & passion.
Feel free to comments, If you have any issues & queries.
Top comments (6)
Hi Sadhan, Initially Thanks a lot for the sharing knowledge, I follow you blog, and I have issue, that
I want to get the gmail body retrieve from simple javascript class, just emai body, I already get it , but can not user that in other class, I man without creating any connection I just want to get email body in other class, can I do it ?
Thanks again,
I didn't get your point properly! As far I guess if I not wrong you like to reuse that connection from other classes. I did not try that yet. Let me try first.
Thank you, for such types of motivational comment.
Hope you looking for this.
Hi Sadhan,
Really Thanks for the kind and quick response, Thanks a lot, That's what I asked.
Sounds Good! If you think I can help, feel free to knock me.
Hi Sadhan, is there any way tht we can read email data from one or more particular from address?