首页 > 解决方案 > 通过收件箱文件夹上的我的 vue.js Web 应用程序发送电子邮件,而不是使用不同电子邮件的垃圾邮件文件夹

问题描述

我对 Web 应用程序的电子邮件集成非常陌生,所以在这种情况下请多多包涵……

我在一家初创公司的网站上工作,我目前有一个使用 webpack 模板的 vue.js 前端应用程序,其中包含一个联系表格,供客户联系公司。我还有一个 node.js 后端应用程序,它使用 websocket 从前端应用程序接收数据,我打算用它向初创公司发送带有客户信息的电子邮件。我的目标是能够在不使用传输器电子邮件地址的情况下发送电子邮件,而是使用 from: 对象中的电子邮件地址。我还想确保我的电子邮件不会出现在垃圾邮件文件夹中。

在此示例中,我尝试使用 nodemailer,但电子邮件未显示客户端 s'email,并且电子邮件出现在垃圾文件夹中。

我的前端 vue.js 应用程序:

<template>
    <main id="fullpage">
        <b-form @submit.prevent="validateForm($event)" id="contactForm" autocomplete="off" 
        method="post">
            <section class="section contactForm">   
                <b-form-row>
                    <h1>{{clientMsg}}</h1>
                </b-form-row>
                <b-form-row>
                    <b-col>
                        <input type="radio" name="client" value="individual" @click="IndvClient"> <label for="individual">an individual?</label>
                    </b-col>
                    <b-col>
                        <input type="radio" name="client" value="company" @click="CorporateClient" > <label for="company">a company?</label>
                    </b-col>
                    <b-col cols="12">
                        <a class="steps text-right next" :href="sectionLinks.emailLink">Next</a>
                    </b-col>
                </b-form-row>
            </section>
            <section class="section contactForm">
                <b-row no-gutters>      
                    <b-col>
                        <input type="email" id="usrEmail" placeholder="Email address..." class="text-center" 
                        :pattern="emailValidation" required v-model="email" @mouseout="isValidEmail($event)" autocomplete="off">
                    </b-col>
                </b-row>
                <b-row no-gutters>
                    <b-col cols="6">
                        <a href="#clientType" class="steps text-left">Previous</a>
                    </b-col>
                    <b-col cols="6">
                        <a class="steps text-right next" :href="sectionLinks.nameLink">Next</a>
                    </b-col>
                </b-row>
            </section>
            <section class="section contactForm">
                    <input type="text" name="usrName" id="usrName" placeholder="Name..." class="text-center"
                    required :pattern="textValidation" v-model="name" @mouseout="isValidName($event)" autocomplete="off">
                    <b-row no-gutters>
                        <b-col cols="6">
                            <a href="#email" class="steps text-left">Previous</a>
                        </b-col>
                        <b-col cols="6">
                            <a class="steps text-right next" :href="sectionLinks.titleLink">Next</a>
                        </b-col>
                    </b-row>
            </section>
            <section class="section contactForm">
                    <input type="text" name="msgTitle" id="msgTitle" placeholder="Title of the message..." 
                    class="text-center" v-model="messageTitle" required :pattern="textValidation"
                    @mouseout="isValidTitle($event)" autocomplete="off">
                    <b-row no-gutters>
                        <b-col cols="6">
                            <a href="#name" class="steps text-left">Previous</a>
                        </b-col>
                        <b-col cols="6">
                            <a class="steps text-right next" :href="sectionLinks.msgLink" >Next</a>
                        </b-col>
                    </b-row>
            </section>
            <section class="section contactForm">
                <b-row no-gutters>
                    <b-col cols="12">
                        <textarea name="" id="msgContent" cols="100" rows="7" 
                        placeholder="Message..." v-model="message" required 
                        @mouseout="isValidMsg($event)"></textarea>
                    </b-col>
                </b-row>
                <b-row no-gutters>
                    <b-col cols="6">
                        <a href="#title" class="steps text-left">Previous</a>
                    </b-col>
                    <b-col cols="6">
                        <a class="steps text-right next" :href="sectionLinks.msgSummaryLink">Next</a>
                    </b-col>
                </b-row>  
            </section>
            <section class="section contactForm formSummary">
                    <ul class="prevFormLinks">
                        <li v-for="section in previousLinks">
                            <a :href="section.link">{{section.name}}</a>
                        </li>
                    </ul>
                    <b-form-row>
                        <p>{{clientMsg}}</p>
                    </b-form-row>
                    <b-form-row>
                        <b-col>
                            <input type="radio" name="userClient" value="individual"> <label for="individual">an individual?</label>
                        </b-col>
                        <b-col>
                            <input type="radio" name="userClient" value="company"> <label for="company">a company?</label>
                        </b-col>
                    </b-form-row>
                    <b-form-row>
                        <b-col>
                            <h2>Your email:</h2>
                        </b-col>
                        <b-col>
                            <p>{{email}}</p>
                        </b-col>
                    </b-form-row>
                    <b-form-row>
                        <b-col>
                            <h2>Name:</h2>
                        </b-col>
                        <b-col>
                            <p>{{name}}</p>
                        </b-col>
                    </b-form-row>
                    <b-form-row>
                        <b-col>
                            <h4>Title of the message:</h4>
                        </b-col>
                        <b-col>      
                            <p>{{messageTitle}}</p>
                        </b-col>
                    </b-form-row>
                    <b-form-row>
                        <b-col cols="5" id="msgSummary">
                            <p>{{message}}</p>
                        </b-col>
                    </b-form-row>
                    <b-form-row>
                        <b-col cols="12">
                            <input type="submit" value="Submit!">
                        </b-col>
                    </b-form-row>
            </section>
        </b-form>  
    </main>
</template>
<script>
import fullpage from 'fullpage.js'
import $ from "jquery"
/** 
    Make sure you can then send an email
    Replace the jQuery animations with anime.js or another way of animating.
    There are no previous buttons for the summary section.
    */
    export default {
        data(){
            return {
                "clientMsg":this.$store.state.contact.TypeOfClientMsg,
                "name":"",
                "email":"",
                "messageTitle":"",
                "message":"",
                "emailValidation":"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$",
                "textValidation":"[a-zA-Z ]+",
                "sectionLinks":{
                    "clientLink":"#clientType",
                    "emailLink":"#email",
                    "nameLink": "#name",
                    "titleLink":"#title",
                    "msgLink":"#message",
                    "msgSummaryLink":"#messageSummary"
                },
                "previousLinks":[
                    {
                        "link":"#clientType",
                        "name":"Client"
                    },
                    {
                        "link":"#email",
                        "name":"Email"
                    },
                    {
                        "link":"#name",
                        "name":"Name"
                    },
                    {
                        "link":"#title",
                        "name":"Title"
                    },
                    {
                        "link":"#message",
                        "name":"Message"
                    }
                ],
                "companyEmail":"salay777@hotmail.co.uk"
            }
        },
        methods:{
            IndvClient:function(){
                    let ind = document.querySelectorAll('input[value="individual"]');
                    let company = document.querySelectorAll('input[value="company"]'),
                    goToEmail = document.querySelector('a[href="#email"]');
                    (ind[0].checked == true)? ind[1].checked = true : ind[1].checked = false;
                    $(goToEmail).fadeIn();
            },
            CorporateClient:function(){
                    let ind = document.querySelectorAll('input[value="individual"]');
                    let company = document.querySelectorAll('input[value="company"]'),
                    goToEmail = document.querySelector('a[href="#email"]');
                    (company[0].checked == true)? company[1].checked = true : company[1].checked = false;
                    $(goToEmail).fadeIn();
            },
            isValidEmail:function(e){
                let goToName = document.querySelector('a[href="#name"]');
                (e.target.checkValidity())? $(goToName).fadeIn() : $(goToName).fadeOut();
            },
            isValidName:function(e){
               let goToTitle = document.querySelector('a[href="#title"]');
               (e.target.checkValidity())? $(goToTitle).fadeIn() : $(goToTitle).fadeOut();
            },
            isValidTitle:function(e){
                let goToMsg = document.querySelector('a[href="#message"]');
                (e.target.checkValidity())? $(goToMsg).fadeIn() : $(goToMsg).fadeOut();
            },
            isValidMsg:function(e){
                let goToSummary = document.querySelector('a[href="#messageSummary"]');
                (e.target.checkValidity())? $(goToSummary).fadeIn() : $(goToSummary).fadeOut();
            },
            validateForm:function(e){
                let idvClient = document.querySelector('input[value="individual"]'),
                corporateClient = document.querySelector('input[value="company"]'),
                usrEmail = document.getElementById('usrEmail'), usrName = document.
                getElementById('usrName'), msgTitle = document.getElementById('msgTitle'),
                msgContent = document.getElementById('msgContent'), 
                socket = io.connect('http://localhost:5000/');


                if(idvClient.checked !== corporateClient.checked){
                    console.log('client has been checked');
                    if(usrEmail.checkValidity() == false || usrName.checkValidity() == false ||
                        msgTitle.checkValidity() == false || msgContent.checkValidity() == false){
                            e.preventDefault();
                        } else {
                            let email = {
                                    client :"",
                                    email: this.email,
                                    name: this.name,
                                    title: this.messageTitle,
                                    message: this.message
                            };
                            if(idvClient.checked){
                                email.client = "[IDV]";
                            }
                            if(corporateClient.checked){
                                email.client = "[CO]";
                            }

                            socket.emit('email',email);
                            alert('submitted!');
                        }
                } else {
                    console.log('you need to select a client type');
                    e.preventDefault();
                }
            }
        },
        mounted(){
                let idvClient = document.querySelector('input[value="individual"]'),
                corporateClient = document.querySelector('input[value="company"]'),
                goToEmail = document.querySelector('a[href="#email"]'), form =
                document.querySelector('form');

                form.setAttribute('autocomplete', 'off');

                if(idvClient.checked == corporateClient.checked){
                    goToEmail.style.display = 'none';
                }
        }
    };
</script>
<style>

html body #fullpage {
    background-color:#383838 !important; 
    background-image: none !important;
}

html, body,#fullpage {
    overflow: hidden !important;
}
 .fp-tableCell{
  text-align:center;
  display:flex;
  justify-content: center; 
  align-items: center;
  flex-direction: column;

}

 .contactDetails .row {
   margin:0px;
 }

.contactForm .form-row {
  min-width:500px;
  justify-content:center;
}

.contactForm .form-row a, .contactForm .row a {
    margin: 60px;
    text-decoration: none;
    color: #f4f4f4;
    font-size: 36px;
    font-weight: 100;
    transition: color .5s, font-size .2s;
}

.contactForm .form-row a:hover, .contactForm .row a:hover {
    color:orange;
    font-size:40px;
}

#menu {
    display: none !important;
}

button {
    margin-top:20px;
}

h1, h2, h3 , h4 {
    font-weight:100;
}

.next {
    display: none;
}

#msgSummary {
    word-wrap: break-word;
    text-align:left;
}

.formSummary, .formSummary h2 , .formSummary h4, 
.formSummary p {
    text-align:left !important;
}

.prevFormLinks {
    position:absolute;
    left:30px;
    text-align:left;
    margin:0px !important;
    padding:0px;
    color:white !important;
}

.prevFormLinks a {
    font-size:20px !important;
    margin:0px!important;
    padding: 0px !important;
    text-decoration: none;
    color: white !important;
    font-weight:100;
    transition: font-size .25s, color 2s;
}

.prevFormLinks a:hover {
    font-size: 25px !important;
    color: orange !important;
}
</style>

我的后端应用程序的电子邮件模块:

let emailModule = (function(){ let nodemailer = require('nodemailer'), mailOptions = {from:'', to:'', subject:'', text:''};

let transporter = nodemailer.createTransport({
    service : 'gmail',
    auth: {
        user:'projectgorillatransporter@gmail.com',
        pass'*******'
    }
});

let setMailOptions = (from, to, subject, text)=>{
   return new Promise((resolve, reject)=>{
        mailOptions.from = from;
        mailOptions.to = to;
        mailOptions.subject = subject;
        mailOptions.text = text;

        console.log(mailOptions);
        resolve(mailOptions);
        reject(Error('the mailOPtions object was not created'));
   });
};

let sendEmail = (mailOptions)=>{
    transporter.sendMail(mailOptions, (err, info)=>{
        if (err) {
            console.log(err);
          } else {
            console.log('Email sent: ' + info.response);
          }
    });
}

    return {
        send : sendEmail,
        setMailOptions : setMailOptions
    }
})(); // end of the email module

module.exports = emailModule;

我负责处理数据的 node.js 服务器:

let express = require('express'), app = express(), path = require('path'),
socket = require('socket.io'), emailModule = require('./email.js');

let server = app.listen(5000, ()=>{
    console.log('listening to requests...');
});


let io = socket(server);

app.get('/', function(req, res) {
    res.sendFile(path.join(__dirname + '/index.html'));
});

io.on('connection', (socket)=>{
    console.log('made a connection!');

    socket.on('email', (data)=>{
        /**
         * Here you need to set your email options which includes the clients email, destination email,
         * subject and the text (the email content).
         */
        emailModule.setMailOptions(data.email,'salay777@hotmail.co.uk', data.client + ' ' + '(' +
        data.name + ')' + ' ' + data.title, data.message).then((mailOpts)=>{
            emailModule.send(mailOpts);
            console.log('email has been sent!');
        });
    });
});

标签: node.jsvue.jswebpackemailnodemailer

解决方案


有 email-templates 和 sendmail,虽然 nodemailer 很简单。你看过前两个包中的任何一个吗?


推荐阅读