'Sending email via app written in Electron/React/TS

I'm trying to implement email/gmail sending mechanism in my application. This is a desktop application with the hosted content written with the help of React and Electron. I've been trying to implement it in a various ways described on the web, using various modules, googleapi etc but always ended up with some weird error and even more enigmatic issue description - the code was usually based on the "Node.js" section of the article. I don't know if I fully understand the architecture side of this problem and if it is even possible to trigger the sending mechanism or is it something that has to be implemented in form of a server-side service. If anyone could shed some light on the issue I would greatly appreciate it as I've already spent too many hours on the issue. Thanks in advance!



Solution 1:[1]

If anyone is using Quasar/Electron and wants to use nodemailer. This works for me. I'm replying to this post because it's relevant to electron. As stated by the original author, nodemailer must be run as a node process and can't be run on the renderer process.

I put the nodemailer code inside the electron-preload.js file (under the src-electron directory).

Electron uses Context Isolation. Therefore, the nodemailer code needs to be put into the electron-preload.js file. Just putting it in any old .vue file will cause an error. The error I was getting was: nodemailer.createTransport is not a function

In order to overcome the Context Isolation, I had to use the Context Bridge as explained in this electron documentation: https://www.electronjs.org/docs/latest/tutorial/context-isolation

For testing purposes, I'm using ethereal.email as suggested in the nodemailer docs.

electron-preload.js:

import { contextBridge } from 'electron'

contextBridge.exposeInMainWorld('myAPI', {
    doAThing: (emailFrom, emailTo, emailSubject, emailHTML) => {
         var nodemailer = require("nodemailer")

 let transporter = nodemailer.createTransport({
    host: "smtp.ethereal.email",
    port: 587,
    secure: false, // true for 465, false for other ports
     auth: {
          user: '[email protected]',
          pass: 'password'
      },
  })
  
    const mailOptions = {
      from: emailFrom, 
      to: emailTo,
      subject: emailSubject,
      html: emailHTML,
    }
  
    transporter.sendMail(mailOptions, function (err, info) {
      if (err) console.log(err);
      else console.log(info);
    })
      console.log("in the PreLoad Script")
    }
 }) // end contextBridge.exposeInMainWorld

Then, in my .vue file (I'm calling mine personDetails.vue), I have a button, and when clicks it fires off this method:

 async sendEmailMethodSMTP() {
      myAPI.doAThing(this.emailFrom, this.emailTo, this.emailSubject, this.emailHTML )
    }, // end sendEmailMethodSMTP

I'm collecting the variable information in the information I'm passing from the .vue file (this.emailFrom, this.emailTo, this.emailSubject, this.emailHTML), to the doAThing method in the electron-proload.js file.

When the button is pressed, the information is passed to the preloader, nodemailer is fired off, and the email is sent.

I have not compiled my Quasar/Electron app to make sure this works in a live environment, but running quasar in dev mode this is working great.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Cynthia