Category: 10. Nodemailer

https://static.vecteezy.com/system/resources/previews/044/178/327/non_2x/incoming-message-email-cloud-electronic-mail-storage-server-3d-icon-realistic-illustration-vector.jpg

  • Handling Bounces and Complaints

    If you need to handle email bounces or complaints, integrate with email services that provide webhook support. Services like Mailgun and SendGrid offer webhook integrations for these purposes.

    Setting Up Webhooks with Mailgun:

    1. Configure Mailgun Webhooks: Go to the Mailgun dashboard and set up webhooks for events like bounces or complaints.
    2. Create a Webhook Endpoint:
    const express = require('express'); const app = express(); app.use(express.json()); app.post('/webhooks/mailgun', (req, res) => { const event = req.body; console.log('Mailgun Event:', event); // Handle different types of events (e.g., bounces, complaints) res.status(200).send('Webhook received'); }); app.listen(3000, () => { console.log('Server listening on port 3000'); });
  • Customizing Email Headers

    For specific use cases, you might need to add custom headers to your emails. This can be useful for tracking or integrating with other systems.

    Adding Custom Headers:

    let mailOptions = {
    
    from: '"Your Name" <[email protected]>',
    to: '[email protected]',
    subject: 'Custom Header Example',
    text: 'This email has custom headers.',
    headers: {
        'X-Custom-Header': 'CustomHeaderValue',
        'X-Another-Header': 'AnotherHeaderValue'
    }
    }; transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
        return console.error('Error sending email:', error);
    }
    console.log('Email sent:', info.response);
    });
  • OAuth2 Authentication

    For more secure authentication, especially with Gmail, you can use OAuth2. This avoids hardcoding credentials and enhances security.

    Setting Up OAuth2:

    1. Create OAuth2 Credentials: Go to the Google Developer Console and create OAuth2 credentials.
    2. Install Required Libraries:
    npm install googleapis nodemailer
    1. Configure Nodemailer with OAuth2:
    const nodemailer = require('nodemailer'); const { google } = require('googleapis'); const oAuth2Client = new google.auth.OAuth2( process.env.CLIENT_ID, process.env.CLIENT_SECRET, 'https://developers.google.com/oauthplayground' ); oAuth2Client.setCredentials({ refresh_token: process.env.REFRESH_TOKEN }); const sendMail = async () => { try { const accessToken = await oAuth2Client.getAccessToken(); const transporter = nodemailer.createTransport({ service: 'gmail', auth: { type: 'OAuth2', user: process.env.EMAIL_USER, clientId: process.env.CLIENT_ID, clientSecret: process.env.CLIENT_SECRET, refreshToken: process.env.REFRESH_TOKEN, accessToken: accessToken.token } }); const mailOptions = { from: 'Your Name <[email protected]>', to: '[email protected]', subject: 'Hello OAuth2', text: 'This is an email sent using OAuth2 authentication.' }; const result = await transporter.sendMail(mailOptions); console.log('Email sent:', result); } catch (error) { console.error('Error sending email:', error); } }; sendMail();
  • Email Templates with Dynamic Content

    For more dynamic content within email templates, you can use template engines with placeholders. For instance, you can use Handlebars or Pug for advanced templating.

    Example with Handlebars and Nodemailer:

    Install Handlebars:

    npm install handlebars nodemailer-express-handlebars
    

    Set Up Handlebars:

    const nodemailer = require('nodemailer');
    const hbs = require('nodemailer-express-handlebars');
    const path = require('path');
    
    // Create a transporter object
    let transporter = nodemailer.createTransport({
    
    service: 'gmail',
    auth: {
        user: process.env.EMAIL_USER,
        pass: process.env.EMAIL_PASS
    }
    }); // Configure Handlebars transporter.use('compile', hbs({
    viewEngine: {
        extName: '.hbs',
        layoutsDir: path.resolve('./views/'),
        defaultLayout: 'template',
    },
    viewPath: path.resolve('./views/'),
    extName: '.hbs'
    })); // Email options let mailOptions = {
    from: '"Your Name" &lt;[email protected]>',
    to: '[email protected]',
    subject: 'Welcome!',
    template: 'welcome', // 'welcome.hbs'
    context: {
        name: 'John Doe',
        activationLink: 'https://example.com/activate?token=123456'
    }
    }; // Send email transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
        return console.error('Error sending email:', error);
    }
    console.log('Email sent successfully:', info.response);
    });

    Template File (views/welcome.hbs):

    <!DOCTYPE html>
    <html>
    <head>
    
    &lt;title>Welcome {{name}}&lt;/title>
    </head> <body>
    &lt;h1>Welcome, {{name}}!&lt;/h1>
    &lt;p>Please activate your account by clicking &lt;a href="{{activationLink}}">here&lt;/a>.&lt;/p>
    </body> </html>
  • Rate Limiting and Throttling

    When sending a large number of emails, implement rate limiting or throttling to avoid being marked as spam or hitting rate limits of your email provider. Libraries like bottleneck can help with this.

    Example with Bottleneck:

    const Bottleneck = require('bottleneck');
    const limiter = new Bottleneck({
    
    maxConcurrent: 2,
    minTime: 500 // milliseconds
    }); const sendEmail = limiter.wrap(async (emailOptions) => {
    await transporter.sendMail(emailOptions);
    }); // Add jobs to send emails sendEmail({ to: '[email protected]', subject: 'Throttled Email', text: 'This email is sent with throttling.' });
  • Sending Emails from Multiple Accounts

    If you need to send emails from multiple accounts, create multiple transporters and choose one based on the recipient or other criteria.

    const transporter1 = nodemailer.createTransport({
    
    service: 'gmail',
    auth: {
        user: '[email protected]',
        pass: 'password1'
    }
    }); const transporter2 = nodemailer.createTransport({
    service: 'yahoo',
    auth: {
        user: '[email protected]',
        pass: 'password2'
    }
    }); // Use the appropriate transporter based on some logic const transporter = someCondition ? transporter1 : transporter2;
  • Testing Emails

    To test email functionality without sending real emails, use services like Mailtrap or Ethereal. These services provide a fake SMTP server to capture and view emails.

    Configure Mailtrap:

    let transporter = nodemailer.createTransport({
    
    host: 'smtp.mailtrap.io',
    port: 2525,
    auth: {
        user: process.env.MAILTRAP_USER,
        pass: process.env.MAILTRAP_PASS
    }
    });
  • Email Logging and Tracking

    If you need to track email opens or clicks, integrate with an email tracking service or use webhooks. Services like Mailgun or SendGrid provide these features.

    Example with Mailgun:

    const mailgun = require('mailgun-js');
    const mg = mailgun({ apiKey: process.env.MAILGUN_API_KEY, domain: process.env.MAILGUN_DOMAIN });
    
    const data = {
    
    from: 'Your Name &lt;[email protected]>',
    to: '[email protected]',
    subject: 'Hello',
    text: 'Hello world!'
    }; mg.messages().send(data, (error, body) => {
    if (error) {
        console.error('Error sending email:', error);
    } else {
        console.log('Email sent successfully:', body);
    }
    });
  • Handling Large Attachments

    For sending large attachments, consider using a file hosting service like AWS S3 and include a link to the file in your email instead of attaching the file directly.

    Example:

    let mailOptions = {
    
    from: '"Your Name" &lt;[email protected]>',
    to: '[email protected]',
    subject: 'Large File',
    text: 'Please download the file from the following link: https://s3.amazonaws.com/your-bucket/large-file.zip',
    html: '&lt;p>Please download the file from the following link: &lt;a href="https://s3.amazonaws.com/your-bucket/large-file.zip">Download&lt;/a>&lt;/p>'
    };
  • Using Email Queues

    To handle high volumes of emails or to ensure reliable delivery, consider using an email queue. Libraries like Bull or Agenda can help with this.

    Example using Bull:

    Install Bull and Redis:

    npm install bull
    

    Set up a Bull queue:

    const Bull = require('bull');
    const nodemailer = require('nodemailer');
    const redis = require('redis');
    
    // Create a Redis client
    const redisClient = redis.createClient();
    
    // Create a Bull queue
    const emailQueue = new Bull('email', { redis: redisClient });
    
    // Create a transporter object
    const transporter = nodemailer.createTransport({
    
    service: 'gmail',
    auth: {
        user: process.env.EMAIL_USER,
        pass: process.env.EMAIL_PASS
    }
    }); // Process email jobs emailQueue.process(async (job) => {
    const { to, subject, text } = job.data;
    await transporter.sendMail({ from: process.env.EMAIL_USER, to, subject, text });
    }); // Add a job to the queue emailQueue.add({
    to: '[email protected]',
    subject: 'Queued Email',
    text: 'This email was sent using a Bull queue.'
    });