=x= 🌵 CONTACT Page 寄信页的後端寄信功能及其它注意事项。
📌 如同现实世界,如果要寄出一封信,你会需要邮局的服务,而当你要寄出 email 你就需要一个邮件服务器来替你服务,会选择 Google 提供的服务,是因为它简单、安全且免费,而 SMTP (Simple Mail Transfer Protocol) 可以把它当成传送 email 的一种共通规定,实际使用上只需要宣告你要用这种方式进行传送即可,网路上已有相当多介绍寄信作法的文章,本文将简单介绍实作时的过程,并在文末总结後端制作 CONTACT Page 时的其它注意事项。
👀 设定方式可参考 : 如何使用Google SMTP寄信(两段式验证+应用程序密码)
🌵 产生的16码应用程序密码会在稍後用到。
🌵 如果帐户有忘记密码重新设定,16码应用程序密码会被清掉,需要再生成一次。
👺 原本在建立功能时并没有启用两步骤验证及设定应用程序密码,只有依网路的教学在帐号的安全性设定里,设定启用"允许安全性较低的应用程序" (开启两步骤验证後即失效)
,一开始都可以正常使用寄信功能,但不久後就出现错误,爬文并测试发现如果关闭防毒时寄信功能就正常,依网路建议设定两步骤验证及应用程序密码後就可正常使用,而且无需开启低安全性也不用关闭防毒。
(未设定应用程序密码遇到的错误)
<head>
及 <body>
中的内容。
<form>
标签,保留新建时的 <form>
标签,删除来自 .html 内的 <form>
(复制原设定到保留的标签内)<form runat="server" method="post" name="aspnetForm" id="aspnetForm">
action="contact.aspx"
需要拿掉,否则只会直接跳转刷新页面,无法进入送出信件的按键事件。<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTM4NzgwOTUzNw8WAh4HQ2FwdGNoYQUEMzc5ORYCZg9kFgICAw9kFgICAQ9kFgYCBw8QDxYCHgtfIURhdGFCb3VuZGdkEBUIA1VTQQRBU0lBBkVVUk9QRQ1OT1JUSCBBTUVSSUNBD0NFTlRSQUwgQU1FUklDQQ1TT1VUSCBBTUVSSUNBBkFGUklDQQdPQ0VBTklBFQgDVVNBBEFTSUEGRVVST1BFDU5PUlRIIEFNRVJJQ0EPQ0VOVFJBTCBBTUVSSUNBDVNPVVRIIEFNRVJJQ0EGQUZSSUNBB09DRUFOSUEUKwMIZ2dnZ2dnZ2dkZAIJDxAPFgIfAWdkEBUHCVRheWFuYSAzNwlUYXlhbmEgNDYJVGF5YW5hIDQ4GlRheWFuYSA1NCAgIChOZXcgQnVpbGRpbmcpCVRheWFuYSA1OAlUYXlhbmEgNjQISVNBUkEgNTAVBwlUYXlhbmEgMzcJVGF5YW5hIDQ2CVRheWFuYSA0OBpUYXlhbmEgNTQgICAoTmV3IEJ1aWxkaW5nKQlUYXlhbmEgNTgJVGF5YW5hIDY0CElTQVJBIDUwFCsDB2dnZ2dnZ2dkZAINDxYCHgNzcmMFDkpwZWdJbWFnZS5hc2h4ZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WAQUmY3RsMDAkQ29udGVudFBsYWNlSG9sZGVyMSRJbWFnZUJ1dHRvbjG5FQQyUaUwxwcePcF6X9308WUP8w==" />
</div>
<div>
<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="CD2448B2" />
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWFgKR7pRKAt6w6N0JArepvugGAuXBvr8EAo2X6PQHAvHN768EAsylpNwNArDts50HAu3a2roPApiq1MAIArWniMcJApDl3ucMAs7G2I0NAs/GtMoIAtnGtMoIAszJo6EGAtnGwO4BAs3GnJwHAvuDy+cMAu3CxJMMAp/KzpkCAr28ifwM0JmHZRHwnNWAdZdFwWYody60nD0=" />
</div>
<!--表单-->
<div class="from01">
<p>
Please Enter your contact information<span class="span01">*Required</span>
</p>
<br />
<table>
<tr>
<td class="from01td01">Name :</td>
<td><span>*</span><asp:TextBox runat="server" name="Name" type="text" ID="Name" class="{validate:{required:true, messages:{required:'Required'}}}" Style="width: 250px;" required="" aria-required="true" oninput="setCustomValidity('');" oninvalid="setCustomValidity('Required!')" MaxLength="50"></asp:TextBox>
</td>
</tr>
<tr>
<td class="from01td01">Email :</td>
<td><span>*</span><asp:TextBox runat="server" name="Email" type="text" ID="Email" class="{validate:{required:true, email:true, messages:{required:'Required', email:'Please check the E-mail format is correct'}}}" Style="width: 250px;" required="" aria-required="true" oninput="setCustomValidity('');" oninvalid="setCustomValidity('Required!')" MaxLength="50"></asp:TextBox>
</td>
</tr>
<tr>
<td class="from01td01">Phone :</td>
<td><span>*</span><asp:TextBox runat="server" name="Phone" type="text" ID="Phone" class="{validate:{required:true, messages:{required:'Required'}}}" Style="width: 250px;" required="" aria-required="true" oninput="setCustomValidity('');" oninvalid="setCustomValidity('Required!')" MaxLength="50"></asp:TextBox>
</td>
</tr>
<tr>
<td class="from01td01">Country :</td>
<td><span>*</span>
<asp:DropDownList name="Country" id="Country" runat="server" DataTextField="countrySort" DataValueField="countrySort" DataSourceID="SqlDataSource1"></asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:TayanaYachtConnectionString %>" SelectCommand="SELECT [countrySort] FROM [CountrySort]"></asp:SqlDataSource>
</td>
</tr>
<tr>
<td colspan="2"><span>*</span>Brochure of interest *Which Brochure would you like to view?</td>
</tr>
<tr>
<td class="from01td01"> </td>
<td>
<asp:DropDownList name="Yachts" id="Yachts" runat="server" DataTextField="type" DataValueField="type"></asp:DropDownList>
</td>
</tr>
<tr>
<td class="from01td01">Comments:</td>
<td>
<asp:TextBox runat="server" TextMode="MultiLine" name="Comments" Rows="2" cols="20" ID="Comments" Style="height: 150px; width: 330px;" MaxLength="500"></asp:TextBox>
</td>
</tr>
<tr>
<td class="from01td01"> </td>
<td class="f_right">
<!-- Render recaptcha API script -->
<cc1:RecaptchaApiScript ID="RecaptchaApiScript1" runat="server" />
<!-- Render recaptcha widget -->
<cc1:RecaptchaWidget ID="Recaptcha1" runat="server" />
<asp:Label ID="lblMessage" runat="server" Visible="False" ForeColor="Red"></asp:Label>
</td>
</tr>
<tr>
<td class="from01td01"> </td>
<td class="f_right">
<asp:ImageButton runat="server" type="image" name="ImageButton1" id="ImageButton1" src="images/buttom03.gif" style="border-width: 0px;" Height="25px" OnClick="ImageButton1_Click"/>
</td>
</tr>
</table>
</div>
<!--表单-->
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) {
loadModelList();
}
}
private void loadModelList()
{
//1.连线资料库
SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
//2.sql语法
string sql = "SELECT * FROM Yachts";
//3.创建command物件
SqlCommand command = new SqlCommand(sql, connection);
//取得游艇型号分类
connection.Open();
SqlDataReader readerType = command.ExecuteReader();
while (readerType.Read()) {
string typeStr = readerType["yachtModel"].ToString();
string isNewDesign = readerType["isNewDesign"].ToString();
string isNewBuilding = readerType["isNewBuilding"].ToString();
//加入游艇型号下拉选单选项
ListItem listItem = new ListItem();
if (isNewDesign.Equals("True")) {
listItem.Text = $"{typeStr} (New Design)";
listItem.Value = $"{typeStr} (New Design)";
Yachts.Items.Add(listItem);
}
else if (isNewBuilding.Equals("True")) {
listItem.Text = $"{typeStr} (New Building)";
listItem.Value = $"{typeStr} (New Building)";
Yachts.Items.Add(listItem);
}
else {
listItem.Text = typeStr;
listItem.Value = typeStr;
Yachts.Items.Add(listItem);
}
}
connection.Close();
}
🌵 资料库先简易设定要取出的资料,介绍後台实作文章时会详细说明。
👀 SqlDataReader 类别官方参考 : SqlDataReader 类别
👀 .Read() 方法官方参考 : SqlDataReader.Read 方法
<iframe>
的 src 位置。protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
{
if (String.IsNullOrEmpty(Recaptcha1.Response)) {
lblMessage.Visible = true;
lblMessage.Text = "Captcha cannot be empty.";
}
else {
var result = Recaptcha1.Verify();
if (result.Success) {
//验证成功则寄出信件并送出警告提醒
sendGmail();
Response.Write("<script>alert('Thank you for contacting us!');location.href='contact.aspx';</script>");
}
else {
lblMessage.Text = "Error(s): ";
foreach (var err in result.ErrorCodes) {
lblMessage.Text = lblMessage.Text + err;
}
}
}
}
👀 微软内建的 System.Net.Mail.SmtpClient 不建议使用,官方说明 : SmtpClient 类别
👀 System.Net.Mail官网 说明 : System.Net.Mail 命名空间
using MailKit.Net.Smtp;
using MimeKit;
public void sendGmail()
{
//宣告使用 MimeMessage
var message = new MimeMessage();
//设定发信地址 ("发信人", "发信 email")
message.From.Add(new MailboxAddress("TayanaYacht", "[email protected]"));
//设定收信地址 ("收信人", "收信 email")
message.To.Add(new MailboxAddress(Name.Text.Trim(), Email.Text.Trim()));
//寄件副本email
message.Cc.Add(new MailboxAddress("收信人名称", "[email protected]"));
//设定优先权
//message.Priority = MessagePriority.Normal;
//信件标题
message.Subject = "TayanaYacht Auto Email";
//建立 html 邮件格式
BodyBuilder bodyBuilder = new BodyBuilder();
bodyBuilder.HtmlBody =
"<h1>Thank you for contacting us!</h1>" +
$"<h3>Name : {Name.Text.Trim()}</h3>" +
$"<h3>Email : {Email.Text.Trim()}</h3>" +
$"<h3>Phone : {Phone.Text.Trim()}</h3>" +
$"<h3>Country : {Country.SelectedValue}</h3>" +
$"<h3>Type : {Yachts.SelectedValue}</h3>" +
$"<h3>Comments : </h3>" +
$"<p>{Comments.Text.Trim()}</p>";
//设定邮件内容
message.Body = bodyBuilder.ToMessageBody(); //转成邮件内容格式
using (var client = new SmtpClient()) {
//有开防毒时需设定 false 关闭检查
client.CheckCertificateRevocation = false;
//设定连线 gmail ("smtp Server", Port, SSL加密)
client.Connect("smtp.gmail.com", 587, false); // localhost 测试使用加密需先关闭
// Note: only needed if the SMTP server requires authentication
client.Authenticate("[email protected]", "16码应用程序密码");
//发信
client.Send(message);
//结束连线
client.Disconnect(true);
}
}
👺 如有用using System.Net.Mail
记得删除,因为 MailKit 也有同名的 SmtpClient 。
👀 MailKit 说明 : GitHub - MailKit
👀 MimeKit 说明 : GitHub - MimeKit
📢 今天实作的下拉选单是自己取资料的作法,里面的国家分类没有要做特殊处理,其实可以用页面设计精灵制作,在 HTML 页面修改就可以达到相同效果,不用在後置程序码自己写,之後的文章会介绍如何使用精灵绑定资料库资料。
因为自己常记不住HTTP的几个动词所以自己来这边写一下 因为目前还没做出自己的网出来所以会偏向在IT...
啓程的原因? 关於让你出发去旅行的原因是什麽呢? 人际关系交流?家庭工作上的安排?个人的探索?还是其...
从第三天灌好程序之後,也是过了快两个礼拜才使用他,想必每个夜晚他在硬碟里偷偷哭泣,让你的硬碟很潮,比...
-简单的定量风险分析 曝露系数 (EF) 曝露系数 (EF) 是在实现特定威胁时对特定资产的主观、...
上一篇我们的基因体时代-AI, Data和生物资讯 Day28-COVID大数据:资料哪里来 开始进...