38

I have code that send email with nodemailer in nodejs but I want to attach file to an email but I can't find way to do that I search on net but I could't find something useful.Is there any way that I can attach files to with that or any resource that can help me to attach file with nodemailer?

var nodemailer = require('nodemailer');
var events = require('events');
var check =1;
var events = new events.EventEmitter();
var smtpTransport = nodemailer.createTransport("SMTP",{
    service: "gmail",
    auth: {
        user: "example@gmail.com",
        pass: "pass"
    }
});
function inputmail(){
    ///////Email
    const from = 'example<example@gmail.com>';
    const to  = 'example@yahoo.com';
    const subject  = 'example';
    const text = 'example email';
    const html = '<b>example email</b>';
    var mailOption = {
        from: from,
        to:  to,
        subject: subject,
        text: text,
        html: html
    }
    return mailOption;
}
function send(){
        smtpTransport.sendMail(inputmail(),function(err,success){
        if(err){
            events.emit('error', err);
        }
        if(success){
            events.emit('success', success);
        }
    });
}
///////////////////////////////////
send();
events.on("error", function(err){
    console.log("Mail not send");
    if(check<10)
        send();
    check++;
});
events.on("success", function(success){
    console.log("Mail send");
});
DanialV
  • 513
  • 1
  • 4
  • 7

9 Answers9

96

Include in the var mailOption the key attachments, as follow:

var mailOptions = {
...
attachments: [
    {   // utf-8 string as an attachment
        filename: 'text1.txt',
        content: 'hello world!'
    },
    {   // binary buffer as an attachment
        filename: 'text2.txt',
        content: new Buffer('hello world!','utf-8')
    },
    {   // file on disk as an attachment
        filename: 'text3.txt',
        path: '/path/to/file.txt' // stream this file
    },
    {   // filename and content type is derived from path
        path: '/path/to/file.txt'
    },
    {   // stream as an attachment
        filename: 'text4.txt',
        content: fs.createReadStream('file.txt')
    },
    {   // define custom content type for the attachment
        filename: 'text.bin',
        content: 'hello world!',
        contentType: 'text/plain'
    },
    {   // use URL as an attachment
        filename: 'license.txt',
        path: 'https://raw.github.com/andris9/Nodemailer/master/LICENSE'
    },
    {   // encoded string as an attachment
        filename: 'text1.txt',
        content: 'aGVsbG8gd29ybGQh',
        encoding: 'base64'
    },
    {   // data uri as an attachment
        path: 'data:text/plain;base64,aGVsbG8gd29ybGQ='
    }
 ]}

Choose the option that adjust to your needs.

Link:Nodemailer Repository GitHub

Good Luck!!

iLuvLogix
  • 5,920
  • 3
  • 26
  • 43
Harry Martel
  • 1,207
  • 8
  • 6
7

Your code is almost right, just need to add, "attachments" property for attaching the files in your mail,

YOUR mailOption:

var mailOption = {
        from: from,
        to:  to,
        subject: subject,
        text: text,
        html: html
}

Just add attachments like

var mailOption = {
        from: from,
        to:  to,
        subject: subject,
        text: text,
        html: html,
        attachments: [{
            filename: change with filename,
            path: change with file path
        }]
}

attachments also provide some other way to attach file for more information check nodemailer community's documentation HERE

Dhaval
  • 868
  • 12
  • 22
3

If you are passing options object in mail composer constructor and attachment is on http server then it should look like:

const options = {
    attachments = [
      { // use URL as an attachment
        filename: 'xxx.jpg',
        path: 'http:something.com/xxx.jpg'
      }
    ]
}
2
var express = require('express');
var router = express(),
multer = require('multer'),
upload = multer(),
fs = require('fs'),
path = require('path');
nodemailer = require('nodemailer'),

directory = path.dirname("");
var parent = path.resolve(directory, '..');
// your path to store the files
var uploaddir = parent + (path.sep) + 'emailprj' + (path.sep) + 'public' + (path.sep) + 'images' + (path.sep);
/* GET home page. */
router.get('/', function(req, res) {
res.render('index.ejs', {
    title: 'Express'
});
});

router.post('/sendemail', upload.any(), function(req, res) {

var file = req.files;
console.log(file[0].originalname)
fs.writeFile(uploaddir + file[0].originalname, file[0].buffer,     function(err) {
    //console.log("filewrited")
    //console.log(err)
})
var filepath = path.join(uploaddir, file[0].originalname);
console.log(filepath)
    //return false;
nodemailer.mail({
    from: "yourgmail.com",
    to: req.body.emailId, // list of receivers
    subject: req.body.subject + " ✔", // Subject line
    html: "<b>" + req.body.description + "</b>", // html body
    attachments: [{
        filename: file[0].originalname,
        streamSource: fs.createReadStream(filepath)
    }]
});
res.send("Email has been sent successfully");
})
module.exports = router;
1
attachments: [
    {
        filename: "inovices_1.pdf", // the file name 
        path: "https://*************************/invoice/10_9_RMKUns.pdf",// link your file
        contentType: "application/pdf", //type of file
    },
    {
        filename: "inovices_2.pdf",
        path: "https://**************************/invoice/10_9_RMKUns.pdf",
        contentType: "application/pdf",
    },
];

var nodemailer = require("nodemailer");
var all_transporter = nodemailer.createTransport({
    host: process.env.MAIL_SERVICE,
    port: 587,
    auth: {
        user: process.env.MAIL_USER,
        pass: process.env.MAIL_PASS,
    },
    maxConnections: 3,
    pool: true,
});

exports.send_email = function (email, subject, html, extra_cc = [], attachments = []) {
    return new Promise(async (resolve, reject) => {
        var mailOptions = {
            from: process.env.MAIL_FROM_ADDRESS,
            to: email,
            subject: subject,
            html: html,
            cc: [],
        };
        mailOptions["cc"] = mailOptions["cc"].concat(extra_cc);
        if (attachments.length > 0) mailOptions["attachments"] = attachments;
        all_transporter.sendMail(mailOptions, function (error, info) {
            // console.log(error);
            // console.log(info);
            if (error) {
                resolve({ failed: true, err: error });
            } else {
                resolve({ failed: false, data: info.response });
            }
        });
    });
};
Dhaval Italiya
  • 386
  • 2
  • 7
0

The alternative solution is to host your images online using a CDN and link to the online image source in your HTML, eg. <img src="list_image_url_here">.

(I had problems with nodemailer's image embedding using nodemailer version 2.6.0, which is why I figured out this workaround.)

An added benefit of this solution is that you're sending no attachments to nodemailer, so the sending process is more streamlined.

ginna
  • 1,723
  • 1
  • 16
  • 16
0
var mailer = require('nodemailer');
mailer.SMTP = {
    host: 'host.com', 
    port:587,
    use_authentication: true, 
    user: 'you@example.com', 
    pass: 'xxxxxx'
};

Then read a file and send an email :

fs.readFile("./attachment.txt", function (err, data) {

    mailer.send_mail({       
        sender: 'sender@sender.com',
        to: 'dest@dest.com',
        subject: 'Attachment!',
        body: 'mail content...',
        attachments: [{'filename': 'attachment.txt', 'content': data}]
    }), function(err, success) {
        if (err) {
            // Handle error
        }

    }
});
esraa ali
  • 187
  • 1
  • 4
  • 3
    please dont provide code-only answers, explain OP why your code is helping his / her problem – Luca Aug 09 '17 at 08:49
  • This one solved my problem when I didn't want to save files but send to user and then delete – Geek Guy Jan 11 '19 at 20:43
0

Just look at here. Nodemailer > Message configuration > Attachments

The code snippet is below (pdfkit gets the stream):

// in async func
pdf.end();
const stream = pdf;
const attachments = [{ filename: 'fromFile.pdf', path: './output.pdf', 
contentType: 'application/pdf' }, { filename: 'fromStream.pdf', content: stream, contentType: 'application/pdf' }];
await sendMail('"Sender" <sender@test.com>', 'reciver@test.com', 'Test Send Files', '<h1>Hello</h1>', attachments);

Stream uses content not streamSource This bothered me before, share with everyone :)

iFurySt
  • 1
  • 1
0

Reference = https://nodemailer.com/message/attachments/

var mailOption = {
    from: from,
    to:  to,
    subject: subject,
    text: text,
    html: html,
    attachments: [            
        {
            filename: filename,
            path: filePath
        },           
   ]
}