循序漸進BootstrapVue,開發公司門戶網站(3)— 結合郵件發送,收集用戶回饋資訊

在我們公司門戶網站裡面,如果有需要,我們可以提供一個頁面給用戶回饋資訊,以便獲得寶貴的用戶資訊回饋或者一些產品諮詢的記錄,一般這個結合郵件發送到負責人的郵箱即可。本篇隨筆結合後端發送郵件的操作,把相關資訊發送到門戶網站的負責人郵箱裡面。

1、客戶回饋介面

我們這個主題主要介紹BootstrapVue的使用,雖然我們有時候使用了常規的HTML元素,不過也是使用了Bootstrap的樣式來處理介面的。

本篇隨筆繼續介紹BootstrapVue中的表單組件 b-form 及表單元素的使用。在線回饋介面如下所示。

 在這裡主要通過一些常規的數據錄入獲得客戶的回饋即可。

Vue模板的HTML介面程式碼如下所示

<b-form @submit="onSubmit" class="mt-4 mb-5">
  <b-form-group id="input-group-1" label-for="input-1" class="mb-4">
    <b-form-input id="input-1" v-model="form.name" required placeholder="請輸入您的姓名"></b-form-input>
  </b-form-group>

  <b-form-group id="input-group-2" label-for="input-2" class="mb-4">
    <b-form-input id="input-2" v-model="form.phone" required placeholder="請輸入您的手機/郵箱"></b-form-input>
  </b-form-group>

  <b-form-group id="input-group-3" label-for="input-3" class="mb-4">
    <b-form-select id="input-3" v-model="form.suggest" placeholder="回饋類型" :options="suggest" required></b-form-select>
  </b-form-group>

  <b-form-group id="input-group-4" label-for="input-3" class="mb-5">
    <b-form-textarea id="input-4" v-model="form.message" required rows="5" placeholder="請輸入您想說的話"></b-form-textarea>
  </b-form-group>

  <b-button type="submit" block variant="info">提 交</b-button>
</b-form>

而其中data裡面定義了表單對應的數據,如下所示

      form: {
        name: '',
        phone: '',
        suggest: null,
        message: '',
      },
      suggest: [
        { value: null, text: '回饋類型' },
        { value: '需求上報', text: '需求上報' },
        { value: '商務洽談', text: '商務洽談' },
        { value: '意見建議', text: '意見建議' },
        { value: '其它', text: '其它' }
      ],

在數據提交的時候,我們根據正則表達式來判斷一下對應的數據,當然我們也可以使用BootstrapVue的表單驗證控制項來處理,具體可以參考BootstrapVue的表單驗證組件。

async onSubmit (evt) {
  evt.preventDefault()
  const phoneReg = /^1[3456789]\d{9}$/
  const emailReg = /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
  if (!phoneReg.test(this.form.phone) && !emailReg.test(this.form.phone)) {
    this.$bvToast.toast(`提交失敗,請輸入正確的手機號或郵箱號`, {
      title: '提交結果',
      variant: 'danger',
      autoHideDelay: 5000
    })
    return
  }

而其中  this.$bvToast.toast 使用了BootstrapVue 冒泡提示組件。

通過this.$bvToast.toast()Vue組件實例注入從應用程式中的任何位置生成動態toast,而無需在應用程式中放置<b-toast>組件。

使用this.$bvToast.toast()方法生成toasts。該方法接受兩個參數:

  • message: toast主體的內容(字元串或VNodes數組)。必填的。將不會顯示帶有空消息的Toasts。有關將VNodes數組作為消息傳遞的示例,請參閱Advanced usage部分。
  • options: 用於提供標題和/或附加配置選項的可選選項對象。title選項可以是字元串或VNodes數組

options參數接受<b-toast>組件以camelCase name格式而不是kebab case格式接受的大多數道具(staticvisible的除外)。

接著我們收集客戶的資訊,組合後調用後端發送郵件介面,發送郵件即可,最後提示用戶發送是否成功。

      var type = '回饋'
      var html = `
          <p><strong>發信人姓名:</strong></p>
          <p>${this.form.name}</p>
          <p><strong>發信人聯繫方式:</strong></p>
          <p>${this.form.phone}</p>
          <p><strong>發信人回饋類型:</strong></p>
          <p>${this.form.suggest}</p>
          <p><strong>發信人留言:</strong></p>
          <p>${this.form.message}</p>
        `
      const flag = SendMail(html, type)

      if (flag) {
        this.form = {
          name: '',
          phone: '',
          message: ''
        }
        this.$bvToast.toast(`提交成功,我們將儘快與您取得聯繫!`, {
          title: '提交結果',
          variant: 'success',
          autoHideDelay: 5000
        })
      } else {
        this.$bvToast.toast(`提交失敗,請稍後重試!`, {
          title: '提交結果',
          variant: 'danger',
          autoHideDelay: 5000
        })
      }

 

2、郵件的發送處理

關於郵件的發送,之前有參考過 nodemailer,這個使用node環境發送郵件的組件,不過我們現在的BootstrapVue項目的前端不符合這個條件,除非引入 nuxt ,讓頁面先在後端運行再推送給前端展示。

關於nodemailer的學習,可以參考下://github.com/nodemailer/nodemailer,或者官網://nodemailer.com/about/

它的使用程式碼如下所示:

"use strict";
const nodemailer = require("nodemailer");

// async..await is not allowed in global scope, must use a wrapper
async function main() {
  // Generate test SMTP service account from ethereal.email
  // Only needed if you don't have a real mail account for testing
  let testAccount = await nodemailer.createTestAccount();

  // create reusable transporter object using the default SMTP transport
  let transporter = nodemailer.createTransport({
    host: "smtp.ethereal.email",
    port: 587,
    secure: false, // true for 465, false for other ports
    auth: {
      user: testAccount.user, // generated ethereal user
      pass: testAccount.pass, // generated ethereal password
    },
  });

  // send mail with defined transport object
  let info = await transporter.sendMail({
    from: '"Fred Foo 👻" <[email protected]>', // sender address
    to: "[email protected], [email protected]", // list of receivers
    subject: "Hello ✔", // Subject line
    text: "Hello world?", // plain text body
    html: "<b>Hello world?</b>", // html body
  });

  console.log("Message sent: %s", info.messageId);
  // Message sent: <[email protected]>

  // Preview only available when sending through an Ethereal account
  console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
  // Preview URL: //ethereal.email/message/WaQKMgKddxQDoou...
}

不過前面說了,我們不使用這個,就一筆帶過,談談我們後端使用ABP介面發送郵件的處理吧。

我們前端封裝一個調用後端介面發送郵件的通用處理函數,如下所示。

function privateSendEmail(email, subject, body) {
  var data = {
    email,
    subject,
    body
  }
  return request({
    url: '/abp/services/app/Account/SendEmail',
    method: 'post',
    data: data
  })
}

再簡單封裝一下發送回饋資訊的郵件操作函數,如下所示。

export async function SendMail(html, type) { //發送郵件
  type = type || '回饋'
  const mailOptions = {
    from: `一條來自【廣州愛奇迪】網站的${type} wuhuacong@163.com`,
    to: '[email protected]',
    subject: `一條來自【廣州愛奇迪】網站的${type}`, //郵件標題
    html, //郵件內容

  var email = '[email protected]'
  var subject = `一條來自【廣州愛奇迪】網站的${type}`

  var result = false
  await privateSendEmail(email, subject, html).then(data => {
    result = data.success

    return result
  })
}

這樣我們在組件裡面,直接引入這個封裝函數進行調用即可。

import { SendMail } from '@/api/system/mail'

最後發送操作。

 再次回到後端的ABP郵件發送介面上,我之前在隨筆《循序漸進VUE+Element 前端應用開發(33)— 郵件參數配置和模板郵件發送處理》中介紹過郵件發送的操作,我們ABP框架後端是基於AbpMailkitModule組件進行發送郵件的,只需要配置好相關發送郵件的資訊即可。

Module中初始化中處理下對應的自定義發送和自定義配置項的處理類。

然後在使用的應用服務類中注入對應的郵件發送介面以供使用。

我們簡單定義一個發送郵件的DTO對象,用來接收來自客戶的回饋資訊,如下所示。

    /// <summary>
    /// 常規郵件資訊
    /// </summary>
    public class SendEmailDto
    {
        [Required]
        [MaxLength(AbpUserBase.MaxEmailAddressLength)]
        public string Email { get; set; }

        /// <summary>
        /// 內容
        /// </summary>
        [Required]
        public string Body { get; set; }

        /// <summary>
        /// 標題
        /// </summary>
        [Required]
        public string Subject { get; set; }

    }

最後直接發送郵件處理即可。

        /// <summary>
        /// 發送常規郵件內容
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SendEmail(SendEmailDto input)
        {
            await _emailSender.SendAsync(new System.Net.Mail.MailMessage
            {
                To = { input.Email },
                Subject = input.Subject,
                Body = input.Body,
                IsBodyHtml = true
            });

            LogHelper.Logger.Info($"校驗郵件發送給:{input.Email}, 發送郵件成功");
        }

發送處理後,我們就會在郵箱中收到郵件資訊,如下所示。

 以上只是簡單對用戶資訊進行收集,我們如果在系統各種常規的處理中,也可以通過郵件和系統用戶進行資訊通知,如找回密碼、更新密碼,重要操作、工作提醒通知等等操作。