DEV Community

Cover image for SMTP.js – Send Email without a Server from the Browser
Scofield Idehen
Scofield Idehen

Posted on • Originally published at blog.learnhub.africa

SMTP.js – Send Email without a Server from the Browser

Sending email directly from the browser without needing a backend server is now possible using SMTP.js. SMTP.js is a JavaScript SMTP client library that allows you to send mail through client-side JavaScript by wrapping the SMTP protocol.

In this post, we'll cover how to get started with SMTP.js, its features, use cases, and some frequently asked questions on using a JavaScript SMTP library.

Follow this guide to learn How to Scrap LinkedIn Company Data using Voyager Api.

Why Send Email from the Browser?

Here are some reasons you may want to send email directly from the browser without a backend server:

  • No server dependencies - You don't need to rely on a server language like PHP or Node.js to send mail. The entire email process can be handled client-side.
  • Faster prototyping - You can quickly build and iterate on a contact form or newsletter subscription without needing backend code.
  • Reduced server load - Sending mail client-side reduces the load on your servers.
  • Increased privacy - Email contents stay isolated in the browser and aren't sent to your servers.
  • Offline functionality - Emails can still be drafted and sent when offline or on poor connections. They will queue and send when a connection is re-established.

Limitations of Client-Side Email

There are some limitations to keep in mind:

  • No server-side templates - You lose the ability to leverage templating engines like Pug or Handlebars. HTML email needs to be crafted client-side.
  • No server-side storage - You won't have a server log of sent mail. Client-side storage like IndexedDB can be used instead.
  • Spam prevention - Special care must be taken to prevent spam and abuse without server-side systems like CAPTCHA.
  • Email deliverability - Reputation management is harder without consistent IP addresses and server-side software.

So, while SMTP.js removes backend dependencies, some use cases still lend themselves better to server-side email. But for many front-end-focused, privacy-centric, or offline-first applications, SMTP.js can be a great fit.

LinkedIn Voyager API: The Ultimate Developer’s Guide

Getting Started with SMTP.js

SMTP.js can be installed via npm:

npm install smtp.js

Or included directly in the browser from a CDN like unpkg:

<script src="https://unpkg.com/smtp.js/dist/smtp.min.js"&gt;&lt;/script>

To send a simple test email:

import smtp from 'smtp.js';


const email = {

  from: 'sender@example.com',
  to: 'recipient@example.com',
  subject: 'Test email',
  text: 'This is a test email sent from the browser'

}


smtp.sendMail(email)
  .then(info =&gt; console.log(info))
  .catch(err =&gt; console.error(err)) 
Enter fullscreen mode Exit fullscreen mode

We provide SMTP credentials and call smtp.sendMail() with the email object containing from, to, subject, and text fields.

The promise resolves with info about the message or rejects any errors.

SMTP Provider Credentials

To send real email, SMTP credentials need to be supplied:

const credentials = {
  host: 'smtp.example.com',
  port: 465,
  secure: true, 
  auth: {
    user: 'username',
    pass: 'password'
  }
}
smtp.connect(credentials)
  .then(info =&gt; {
    // connected, credentials OK 
  })
Enter fullscreen mode Exit fullscreen mode

Any SMTP provider can be used, like Gmail, Outlook, or a custom server.

Gmail would look something like:

```javascript">const credentials = {
  host: 'smtp.gmail.com',
  port: 465,
  secure: true,
  auth: {
    user: 'myaccount@gmail.com',
    pass: 'mypassword'
  }
}



Now, credentials are supplied to smtp.connect() before sending mail.
<h4>Sending the Message</h4>
With credentials configured, sending an email follows the same pattern:


```javascript">const email = {

  // sender/recipient

  from: 'sender@example.com',
  to: 'recipient@example.com',


  // email content  

  subject: 'Test email',
  text: 'Email content here' 

}


smtp

  .connect(credentials)
  .then(() =&gt; smtp.sendMail(email))
  .then(info =&gt; console.log('Email sent!'))
  .catch(err =&gt; console.error(err))
Enter fullscreen mode Exit fullscreen mode

The message object can also take HTML email content:

const email = {
  from: 'sender@example.com',
  to: 'recipient@example.com',
  subject: 'HTML email',
  html: '&lt;p&gt;This is an &lt;strong&gt;HTML email&lt;/strong&gt;&lt;/p&gt;'
}
Enter fullscreen mode Exit fullscreen mode

That covers the basics of sending email with SMTP.js! Next we'll look at some more advanced features.

SMTP.js Features

SMTP.js supports several helpful features when sending mail:

  • Multiple Recipients

To send to multiple recipients, pass an array of addresses to:

const email = {
  to: [
    'recipient1@example.com',
    'recipient2@example.com'
  ]
}
Enter fullscreen mode Exit fullscreen mode

CC and BCC fields are also supported:

const email = {
  to: 'main@example.com',
  cc: 'cc@example.com',
  bcc: 'bcc@example.com'
}
Enter fullscreen mode Exit fullscreen mode
  • Attachments

To attach files, pass an array of attachments:

const email = {
  attachments: [
    {filename: 'report.pdf', content: pdfBuffer}
  ] 
}
Enter fullscreen mode Exit fullscreen mode

The content can be a Buffer, ArrayBuffer, Stream, or URL.

  • Custom Headers

Additional headers can be added:

const email = {
  headers: {
    'X-Custom-Header': 'value'  
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Email Queue

To send multiple emails, an internal queue is used:

// add emails to queue
smtp.addMailToQueue(email1);
smtp.addMailToQueue(email2);


// connect and send entire queue
smtp.connect(credentials)
  .then(() =&gt; smtp.flushQueue())
  .catch(err =&gt; console.error(err));
Enter fullscreen mode Exit fullscreen mode

This allows sending a batch of emails efficiently.

  • Custom SMTP Server

Instead of a major provider, you can connect to a custom SMTP server:

const credentials = {
  host: 'mail.yourdomain.com',
  port: 587,
  secure: false,
  auth: {
    user: 'username',
    pass: 'password'    
  }
}
Enter fullscreen mode Exit fullscreen mode

Use any self-hosted SMTP server like Postfix, Sendmail, or Exchange.

This covers the main features of SMTP.js! Next we'll look at some good use cases for sending email from the browser.

When to Use SMTP.js

Several types of applications lend themselves well to using SMTP.js for client-side email:

  • Contact Forms

A common use case is browser-based contact forms:

const form = document.querySelector('#contact-form');


form.addEventListener('submit', event =&gt; {
  event.preventDefault();
  const email = {
    to: 'contact@example.com',
    subject: form.subject.value,
    text: form.message.value
  }

  smtp.sendMail(email)
    .then(() =&gt; form.reset())
    .catch(err =&gt; console.error(err))
});
Enter fullscreen mode Exit fullscreen mode

No server code is needed!

  • Newsletter Signup

For a newsletter signup form, save the email to IndexedDB and queue the confirmation:

form.addEventListener('submit', event =&gt; {
  event.preventDefault();
  const email = form.email.value;
  db.users.add({email});
  const confirmEmail = {
    to: email,
    subject: 'Please confirm signup',
    text: 'Click here to confirm: https://...'
  }
  smtp.addMailToQueue(confirmEmail);
  smtp.flushQueue();
})
Enter fullscreen mode Exit fullscreen mode
  • Online Email Client

SMTP.js allows building a web-based email client or webmail system without servers.

Messages stay local using IndexedDB or other browser storage for the mail client.

  • CRM/Support Platforms

In customer management apps, support agents can respond to tickets directly from the browser:

agentForm.addEventListener('submit', event =&gt; {
  event.preventDefault();
  const {recipient, body} = form;
  smtp.sendMail({
    to: recipient,
    text: body
  });
});
Enter fullscreen mode Exit fullscreen mode

Again, no server-side code is needed for sending responses.

  • Offline Functionality

For offline-first web apps, emails can be queued when offline and sent when a connection is

re-established:

// detect connection state

const isOnline = navigator.onLine;

// queue message

smtp.addMailToQueue(email);

if(isOnline) {

  smtp.flushQueue();

} else {

  window.addEventListener('online', () =&gt; {

    smtp.flushQueue();

  });

}
Enter fullscreen mode Exit fullscreen mode

So SMTP.js enables email functionality even without a network.

These are just a few examples of when sending mail directly from the client can be useful.

Common Questions

Here are answers to some frequently asked questions about using SMTP.js:

How does SMTP.js work without a server?

SMTP.js directly speaks the SMTP protocol to send mail. It is a client-side SMTP "server" connecting to real external servers. All the code is contained in the browser.

Is it secure to send email via client-side code?

SMTP.js is as secure as SMTP itself. All connections use TLS encryption, and credentials are not exposed client-side. The email contents and data stay local to the browser and JavaScript environment.

What is the advantage of a server-side solution?

It depends on the use case, but the advantages include no server dependencies, increased privacy, offline support, and reduced server load for things like contact forms.

What are the limitations?

Limitations include a lack of server-side templates, no central server log of sent mail, and reduced deliverability protections. Complex workflows involving mail merge and sending high volumes of email work better with a server.

How does email get delivered without a static IP address?

Services like Mailgun provide an SMTP API gateway with a consistent sending IP address and domain while masking the underlying client IPs. This helps improve deliverability.

Does SMTP.js work for sending bulk email?

SMTP.js can technically send bulk volumes, but server-side solutions are better suited for large mailing lists and newsletter campaigns. SMTP.js is better optimized for one-off transactional email.

Can SMTP.js connect to any SMTP service?

Yes, SMTP.js can connect to any standard SMTP provider or custom SMTP server with the proper credentials configured. Popular choices include Gmail, Mailgun, SparkPost, Amazon SES, or a self-hosted mail server.

Hopefully, this gives you a better understanding of how to use SMTP.js to send email directly from the browser! Let me know if you have any other questions.

If you find this article thrilling, discover extra thrilling posts like this on Learnhub Blog; we write a lot of tech-related topics from Cloud computing to Frontend Dev, Cybersecurity, AI, and Blockchain. Take a look at How to Build Offline Web Applications. 

Resource

Top comments (24)

Collapse
 
bartoszkrawczyk2 profile image
Bartosz Krawczyk

Exposing your SMTP username and password to front-end sounds like a terrible idea. For quick prototyping, maybe. But for production? Your credentials will be used to send spam in no time.

Collapse
 
artydev profile image
artydev

You can create the email form dynamically from a strongly encrypted js script.
That reduces dammatically the risk.
Please I know, nothing is it 100% secure, neither great firms.

Collapse
 
scofieldidehen profile image
Scofield Idehen

True, Thanks

Collapse
 
bartoszkrawczyk2 profile image
Bartosz Krawczyk

What is strongly encrypted js script? You mean minified?

Thread Thread
 
artydev profile image
artydev

No, truly obfuscated, look here : Obfuscator.
I am using smtp.js in production without any spams.

Thread Thread
 
bartoszkrawczyk2 profile image
Bartosz Krawczyk

But it's still client side code. It still be in memory on user's device. It'll still be in javascript runtime.

Plus, you can easily reverse any obfuscation. Here is one for obfuscator.io:
obf-io.deobfuscate.io/

Thread Thread
 
artydev profile image
artydev • Edited

Yes, indeed...
But all is not lost :-)

Try this : DecryptMe

Hint : before IBM :-)

From PageCrypt

Collapse
 
scofieldidehen profile image
Scofield Idehen • Edited

Everyone has their own poison, wouldn't you agree?

Collapse
 
artydev profile image
artydev

Hy Scofield,
Thank you for this post.

I use smtp.js in my work, it's indeed a great library.
In order to prevent spamming, I create the contact form dynamically.

Collapse
 
scofieldidehen profile image
Scofield Idehen

Cool!!

Collapse
 
artydev profile image
artydev

For the ones who are afraid to use it client side :
You can create the email form dynamically from a strongly encrypted js script.
That reduces dammatically the risk.

Collapse
 
scofieldidehen profile image
Scofield Idehen

Thanks

Collapse
 
istra_daily profile image
Davor

I have a few questions about this librery. I do not think anyone should use this in production. This is maybe a great way to teach your self about e-mail and Javascript.

Issues:

  1. SPF will never be correct. E-mail's will never be delivered on scale. SPF (Sender Policy Framework) is designed to authenticate the sending IP address against the domain used in the email's "From" address. When you send email directly from the client's IP address, it is highly unlikely that this IP will be listed in the SPF record of the sending domain, resulting in SPF validation failure. This makes your emails more likely to be marked as spam or rejected altogether.

  2. IP's get blacklisted and ISP do not clean them. ISPs typically don't proactively remove IPs from blacklists. Once an IP is blacklisted, it requires a manual delisting process, and there is no guarantee of success.

  3. Username and password for an e-mail address in browser. Storing the username and password for an email address in the client-side JavaScript code exposes these credentials to anyone who can inspect the code. This is a major security risk that could lead to unauthorized access to the email account, allowing for a wide range of malicious activities including but not limited to sending spam or phishing emails, reading existing email, and potentially gaining access to other services tied to that email for password recovery.

Collapse
 
scofieldidehen profile image
Scofield Idehen

While this library may have some useful educational purposes, it's important to be aware of the potential drawbacks you highlighted if considering production use cases. There are tradeoffs to evaluate with any email sending approach. Thanks for sharing your thoughtful analysis

Collapse
 
jestingrabbit profile image
Bill C

I would never use this on the client in prod.

Sending emails isn't easy and neutral. You need to make sure that you're not getting marked as spam, that users are opening your emails, especially your transactional emails, eg password resets. You need to verify email addresses you're sending to, and ensure that you're not repeatedly sending to dead mail boxes.

If you don't do these things, you will get marked as a source of spam, and places like google will send your mails to the spam folder. I can't see how you would do any of this important stuff on the client in any way that wasn't serious.

This is all before you start worrying about SPF or a bunch of other things.

Please, don't use this in the client on prod. There are email sending businesses for a reason. Bootstrap without buying their services, send from your own servers if you're being super cheap, but after you've got a thousand users giving you money, buy a service. Its worth it. imo.

Collapse
 
scofieldidehen profile image
Scofield Idehen

All of this is for educational base only. How you use it is left for each user to determine.

I think spam will be there even with paid service and more sophisticated platforms.

For anyone who know what they are doing they will be able to figure it all out.

Thanks and best regards.

Collapse
 
alaxander7 profile image
alaxander7

It also needs proper rendering, which is known as full-featured representation of MVP The whole point of using MVP is to see how your product functions in an environment where people would be using it regularly. App Development Company In Kerala This goes on to help create the focus required for a sustainable business model or Process Driven Development (PDD).

Collapse
 
scofieldidehen profile image
Scofield Idehen • Edited

I guess you are just trying to push the link, however, I have a better idea on creating simple to advance content that would rank and give visibility through Learnhub

Collapse
 
pavelee profile image
Paweł Ciosek

Cool! Great for quick prototyping! 🥳 Thank you! 🙏

Collapse
 
somidad profile image
Jeon • Edited

Does this really keep user credential unexposed?

Plus, I cannot access to npm package and unpkg CDN.

Collapse
 
scofieldidehen profile image
Scofield Idehen

Yes, the documentation says so.

Collapse
 
somidad profile image
Jeon

According to smtpjs.com/, seems like you need encrypted 'secure token' instead of putting username and password to script visible to client as described in this post.

Thread Thread
 
scofieldidehen profile image
Scofield Idehen

It was deprecated and going forward, tokens were introduced, I think SMTP does not have good documentation to transition users.

Collapse
 
cherchercher profile image
Cher Huang

If i put the password and username as environment variables, is that good enough?
how does that compares to obfusticating the javascript file?

Thanks