Bây giờ bạn đã có website dùng hệ thống file phẳng (flat file), bạn muốn nhận phản hồi từ người dùng. Thêm Disqus dễ dàng vì toàn bộ là JavaScript thêm vào trang, nhưng đó không phải điều bạn muốn. Bạn muốn họ email trực tiếp cho bạn để bạn có thể trả lời riêng.
Bạn có thể tạo hệ thống toàn JavaScript để email từ máy người dùng, nhưng điều đó để lộ email của bạn cho spammer lấy từ code và bán cho spammer khác. Do đó, bạn cần ẩn địa chỉ email trên server.
Hướng dẫn này về thêm hệ thống email vào PressCMS mới của bạn (tức phpPress, rubyPress, nodePress, và goPress). Tôi bắt đầu từ front-end rồi xử lý back-end cho từng hệ thống. Giả định bạn đã cài đặt sẵn các server này.
Tạo Form trên trình duyệt
Vì code front-end giống nhau cho mọi server, bạn phải copy file mới này vào thư mục của từng server. Do đó, tôi sẽ nói về file theo đường dẫn tham chiếu từ thư mục server.
Thay vì thêm style riêng cho form vào theme, script form này gom mọi thứ vào một chỗ. Tạo file questions.html trong thư mục site/parts của website với nội dung:
<!-- Styling for the form -->
<style>
form {
margin: 20px auto;
width: 400px;
padding: 1em;
border: 1px solid #f0d5ad;
border-radius: 1em;
}
form div + div {
margin-top: 1em;
}
label {
display: inline-block;
width: 90px;
text-align: right;
}
input, textarea {
width: 300px;
-moz-box-sizing: border-box;
}
input:focus, textarea:focus {
border-color: #000;
}
textarea {
vertical-align: top;
height: 5em;
resize: vertical;
}
button {
margin-top: 10px;
margin-left: 8em;
}
</style>
<!-- HTML for the Form -->
<form action="/api/message" method="post">
<div>
<label for="Name">Name:</label>
<input id="Name" name="Name" type="text" value="" pattern="[a-zA-Z]{3,3} [a-zA-Z]{3,3}" title="First and Last name." autofocus required />
</div>
<div>
<label for="Email">Email:</label>
<input id="Email" name="Email" type="email" pattern="[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}" title="Valid Email only." value="" required />
</div>
<div>
<label for="Message">Message:</label>
<textarea id="Message" name="Message" type="text" value="" required></textarea>
</div>
<button type="submit">Send Message</button>
</form>
Điều này tạo form cơ bản yêu cầu họ tên đầy đủ (first và last name), email, và tin nhắn. Form dùng regex để đảm bảo tên và email hợp lệ. Nếu người dùng nhập không khớp regex trong chỉ thị pattern, form sẽ không submit. Popup sẽ nhờ người dùng điền đúng với thông báo trong tham số title. Mỗi trường input có primitive required. Điều này ngăn form rỗng được submit. Đây là validation dữ liệu tối thiểu bạn nên dùng ở front-end.
Chỉ thị action trong phần tử form nói với trình duyệt địa chỉ submit dữ liệu form. Chỉ thị method nói trình duyệt gửi bằng phương thức post. Dữ liệu form sẽ đặt vào URL của request post đến server. Đây là Query String. Server sau đó xử lý thông tin trong query string.
Trong thư mục site/pages, tạo file contact.md và đặt code này:
### Contact Us
This is a simple contact form. Please fill in your name, first and last, email address, and message. I will get back to you as soon as possible. Thanks.
{{{question}}}
Khi lưu, bạn có thể thử trang trên server. Trên trình duyệt, mở trang https://localhost:8081/contact.
Trang Contact Us sẽ trông như hình trên. Lưu ý trường Name được highlight ngay khi tải. Chỉ thị autofocus tạo hành vi mong muốn này. Luôn là thiết kế tốt khi trường đầu tiên cần nhập được focus tự động.
Sau khi gửi tin nhắn, thông báo xác nhận cho người dùng sẽ hay hơn. Trong thư mục site/pages, tạo file messagesent.md và đặt code này:
### Message was sent Thank you so much for taking time to send me a message. I will reply as soon as possible.
Chỉ một thông báo đơn giản để người dùng biết tin nhắn đã gửi thành công. Bạn có thể mở rộng tùy ý.
Xử lý Form với goPress
Để làm sạch tin nhắn từ người dùng, tôi dùng thư viện Blue Monday. Để tải thư viện trên hệ thống, chạy lệnh:
go get github.com/microcosm-cc/bluemonday
Điều này làm thư viện sẵn sàng cho chương trình. Đó là thư viện non-standard duy nhất cần thiết.
Mở file goPressServer.go và thêm vào phần import () ở đầu file:
"fmt" "github.com/hoisie/web" "net/smtp" "github.com/microcosm-cc/bluemonday"
Gửi email từ server cần các thư viện này. Sau dòng có goPress.DefaultRoutes(, thêm code sau:
// Setup special route for our form processing.
goPress.SetPostRoute('/api/message', postMessage)
Điều này thiết lập post route /api/message chạy hàm postMessage(). Ở cuối file, thêm code này:
// Function: postMessage
// Description: This function will send the message from the website to the owner of the site.
// Inputs: ctx The web server context.
func postMessage(ctx *web.Context) string {
// Get the post information and send the email.
name := ctx.Params["Name"]
from := ctx.Params["Email"]
p := bluemonday.UGCPolicy()
message := p.Sanitize(ctx.Params["Message"])
to := "<your email address>"
subject := "Message from User:" + name + " of CustomCT.com"
sendEmail(to, from, subject, message)
// Get the messagesent page contents and process it.
pgloc := goPress.SiteData.Sitebase + "pages/messagesent"
return goPress.RenderPageContents(ctx, goPress.GetPageContents(pgloc), pgloc)
}
// Function: sendEmail
// Description: This function sends an email message.
// Inputs: to, from, subject, message
func sendEmail(to string, from string, subject string, message string) {
body := fmt.Sprintf("To: %s\r\nSubject: %s\r\n\r\n%s", to, subject, message)
auth := smtp.PlainAuth("", "<your email address>", "<your password>", "smtp.gmail.com")
err := smtp.SendMail("smtp.gmail.com:587", auth, from, []string{to}, []byte(body))
if err != nil {
// Process the error. Currently, assuming there isn't a problem.
}
}
Hai hàm này tạo thành handler xử lý email từ trình duyệt. Route /api/message gọi postMessage(). Nó lấy thông tin từ form, làm sạch tin nhắn với BlueMonday, và gửi email cho chủ sở hữu qua sendEmail(). Bạn phải thay <your email address> bằng Gmail của bạn và <password> bằng mật khẩu.
Trong file goPress.go, thêm hàm này sau SetGetRoute():
// Function: SetPostRoute
// Description: This function gives an easy access to the web variable setup in this library.
// Inputs: route Route to setup, handler Function to run that route.
func SetPostRoute(route string, handler interface{}) {
web.Post(route, handler)
}
Hàm này giống hệt SetGetRoute(). Khác biệt duy nhất là dùng web.Post().
Với thay đổi này, goPress server của bạn giờ có thể gửi email từ người dùng.
Xử lý Form với nodePress
Để gửi email từ Node, bạn cần cài nodemailer và body-parser:
npm install -save nodemailer npm install -save body-parser
Sau đó load thư viện mới và cấu hình mailer object. Ở đầu nodePress.js, sau thư viện cuối cùng, thêm:
var nodemailer = require('nodemailer'); // https://nodemailer.com/
var bodyParser = require('body-parser'); // https://github.com/expressjs/body-parser
// create reusable transporter object using the default SMTP transport
var transporter = nodemailer.createTransport('smtps://<your email name%40<your email domain>:<your password>@smtp.gmail.com');
Điều này load nodemailer và thiết lập component dùng lại cho gửi email. Bạn phải thay <your email name> bằng tên email (phần trước @), <your email domain> là domain email (gmail.com hoặc domain riêng nếu dùng Gmail trên domain), và <your password> bằng mật khẩu tài khoản email.
Sau dòng khởi tạo biến nodePress, thêm:
// Configure the body parser library.
nodePress.use(bodyParser.urlencoded({ extended: true }));
Bây giờ, sau lời gọi nodePress.get() cuối cùng, thêm:
nodePress.post('/api/message', function(request, response) {
// setup e-mail data
var mailOptions = {
from: request.body.Email,
to: '<your email address>',
subject: 'Message from ' + request.body.Name + ' on contact form.',
text: request.body.Message,
html: request.body.Message
};
// Send the email.
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error);
}
// Send the user to the message was sent okay page.
response.send(page("messagesent"));
});
});
Đây là handler cho địa chỉ /api/message. Hàm này lấy thông tin từ form, tạo email phù hợp, và gửi đến email trong <your email address>. Sau khi gửi, chuyển user đến trang /messagesent. Middleware body-parser lưu tham số URL vào request.body và đã sanitized.
Code này hoạt động cho Gmail không có two-factor authentication. Nếu bạn bật 2FA, tham khảo tài liệu Nodemailer để cấu hình.
Xử lý Form với rubyPress
Để gửi email trong Ruby, bạn cần cài ruby-gmail:
gem install ruby-gmail
Tùy thiết lập Ruby, bạn có thể cần sudo trước lệnh. Để load thư viện, thêm dòng này ở đầu rubyPress.rb:
require 'gmail' # https://github.com/dcparker/ruby-gmail
Sau tất cả định nghĩa get, thêm các dòng sau:
post '/api/message' do
# Get the parameters from the form.
name = params[:Name]
email = params[:Email]
message = params[:Message]
# Create and send the email.
Gmail.new('<your email address>', '<your password>') do |gmail|
gmail.deliver do
to "<your email address>"
from email
subject "Message from " + name
text_part do
body message
end
end
end
# Send the user to the message sent page.
page 'messagesent'
end
Với thêm này, rubyPress server có thể xử lý form email. Khi bạn thay <your email address> và <your password> bằng giá trị thực, script hoàn tất.
Xử lý Form với phpPress
Server cuối cần sửa là phpPress. Để thêm khả năng email, tôi cài phpmailer – thư viện PHP phổ biến nhất cho email. Để cài, chạy lệnh sau trong thư mục phpPress:
composer update composer require phpmailer/phpmailer
Thật không may, composer update sẽ cập nhật LightnCandy. Điều này tốt vì nó nhanh hơn và dễ dùng hơn. Nhưng nó làm hỏng code server. Trong file index.php, tìm hàm ProcessPage() và thay bằng code sau:
// Function: ProcessPage
// Description: This function will process a page into the template, process all Mustache macros, and process all shortcodes.
// Inputs: $layout The layout for the page, $page The pages main contents
function ProcessPage( $layout, $page ) {
global $site, $parts, $helpers;
// Get the page contents.
$parts['content'] = figurePage($page);
// First pass on Handlebars.
$phpStr = LightnCandy::compile($layout, $helpers);
$renderer = LightnCandy::prepare($phpStr);
$page = $renderer($parts);
// Process the shortcodes.
$pageShort = processShortcodes($page);
// Second pass Handlebars.
$phpStr = LightnCandy::compile($pageShort, $helpers);
$renderer = LightnCandy::prepare($phpStr);
$page = $renderer($parts);
// Return the results.
return($page);
}
So với code cũ, bạn không còn phải làm việc với file tạm. Tất cả xử lý trong bộ nhớ và do đó nhanh hơn. Bây giờ, ở đầu index.php, thêm sau thư viện Jade:
// PHP Mailer: https://github.com/PHPMailer/PHPMailer require 'vendor/phpmailer/phpmailer/PHPMailerAutoload.php';
Điều này load phpmailer. Bây giờ, sau lời gọi $app->get() cuối cùng, thêm code này:
// This route is for processing the post request from the email form on the website.
$app->post('/api/message', function(Request $request, Response $response) {
global $_POST;
// Get the post variables.
$Name = $_POST['Name'];
$Email = $_POST['Email'];
$Message = $_POST['Message'];
// Create the email message and send it.
$mail = new PHPMailer;
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp.gmail.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = '<your email address>'; // SMTP username
$mail->Password = '<your password>'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
$mail->setFrom($Email, $Name);
$mail->addAddress('<your email>', '<your name>'); // Add a recipient
$mail->Subject = "Message from $Name";
$mail->Body = $Message;
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
$newResponse = SetBasicHeader($response);
$newResponse->getBody()->write(page('messagesent'));
return($newResponse);
}
});
Đây là handler post request cho đường dẫn /api/message. Nó lấy dữ liệu form từ trình duyệt, tạo email, và gửi. PHP tự động lấy tham số URL và đặt vào mảng toàn cục $_POST.
Bạn phải thay <your email address>, <your password>, và <your name> bằng giá trị phù hợp cho email của bạn. Nếu dùng SMTP server khác Gmail, bạn cần thay địa chỉ $mail->Host.
Kết luận
Tôi đã chỉ cho bạn cách dễ dàng thêm form email vào trang pressCMS. File download cho hướng dẫn này có tất cả server với sửa đổi. Bạn có thể tải xuống thay vì gõ tay. Tôi đã làm chút xử lý lỗi. Phần còn lại để bạn tự tập luyện.
Phương pháp tôi dạy ở đây là post form data với dữ liệu trong URL. Nhiều trang hiện nay dùng REST API với dữ liệu trong JSON string trong body để thực hiện hành động. Các routine này dễ dàng thích ứng với phương pháp đó, nhưng đó là bài tập cho bạn (hoặc có thể hướng dẫn tương lai). Bây giờ bạn biết cách làm cách này, hãy thêm form riêng vào trang. Việc tùy biến này rất vui. Giới hạn duy nhất là trí tưởng tượng của bạn.