Như bạn đọc trong bài này, tôi gần đây gặp sự cố với mail server và quyết định outsourcing quản trị email sang Amazon Simple Email Service (SES).
Vấn đề của giải pháp đó là SES lưu tin nhắn mới vào S3 bucket, và dùng AWS Management Console đọc file trong S3 bucket nhanh chán.
Vì vậy tôi quyết định viết script Bash tự động hóa quy trình tải xuống, lưu trữ đúng cách, và xem tin nhắn mới.
Mặc dù script này viết cho Ubuntu Linux desktop, không cần chỉnh sửa nhiều để chạy trên macOS hoặc Windows 10 qua Windows SubSystem for Linux.
Dưới đây là script hoàn chỉnh. Sau khi xem qua, tôi sẽ giải thích từng bước.
#!/bin/bash
# Retrieve new messages from S3 and save to tmpemails/ directory:
aws s3 cp \
--recursive \
s3://bucket-name/ \
/home/david/s3-emails/tmpemails/ \
--profile myaccount
# Set location variables:
tmp_file_location=/home/david/s3-emails/tmpemails/*
base_location=/home/david/s3-emails/emails/
# Create new directory to store today's messages:
today=$(date +"%m_%d_%Y")
[[ -d ${base_location}/"$today" ]] || mkdir ${base_location}/"$today"
# Give the message files readable names:
for FILE in $tmp_file_location
do
mv $FILE ${base_location}/${today}/email$(rand)
done
# Open new files in Gedit:
for NEWFILE in ${base_location}/${today}/*
do
gedit $NEWFILE
done
Bắt đầu với lệnh đơn tải tin nhắn hiện tại trong S3 bucket (đã đổi tên bucket và chi tiết filesystem/auth để bảo mật).
aws s3 cp \
--recursive \
s3://bucket-name/ \
/home/david/s3-emails/tmpemails/ \
--profile myaccount
Đương nhiên, chỉ hoạt động nếu đã cài đặt và cấu hình AWS CLI cho hệ thống local. Làm ngay nếu chưa.
Lệnh cp nghĩa là "copy", --recursive yêu cầu CLI áp dụng thao tác cho nhiều object, s3://bucket-name trỏ đến bucket của tôi (tên bucket của bạn khác), dòng /home/david... là địa chỉ filesystem tuyệt đối để copy tin nhắn, và tham số --profile cho CLI biết tài khoản AWS nào trong nhiều tài khoản của tôi.
Phần tiếp theo đặt hai biến giúp dễ dàng chỉ định vị trí filesystem trong script.
tmp_file_location=/home/david/s3-emails/tmpemails/*
base_location=/home/david/s3-emails/emails/
Chú ý giá trị biến tmp_file_location kết thúc bằng dấu hoa thị. Đó là vì tôi muốn tham chiếu đến file bên trong thư mục đó, không phải thư mục chính nó.
Tôi sẽ tạo thư mục vĩnh viễn mới trong階層 .../emails/ để dễ tìm tin nhắn sau. Tên thư mục mới là ngày hiện tại.
today=$(date +"%m_%d_%Y")
[[ -d ${base_location}/"$today" ]] || mkdir ${base_location}/"$today"
Tôi tạo biến shell mới tên today được điền bởi output của lệnh date +"%m_%d_%Y". date xuất full date/timestamp, nhưng phần sau ("%m_%d_%Y") chỉnh sửa output thành format đơn giản, dễ đọc hơn.
Tôi kiểm tra sự tồn tại của thư mục dùng tên đó - chỉ ra đã nhận email ngày đó và không cần tạo lại thư mục. Nếu thư mục không tồn tại (||), mkdir sẽ tạo giúp. Nếu không chạy test này, lệnh có thể trả về thông báo lỗi phiền toái.
Vì Amazon SES đặt tên xấu, khó đọc cho mỗi tin nhắn thả vào S3 bucket, tôi sẽ đổi tên động chúng đồng thời di chuyển đến nhà mới (trong thư mục theo ngày vừa tạo).
for FILE in $tmp_file_location do mv $FILE ${base_location}/${today}/email$(rand) doneVòng lặp for...do...done đọc từng file trong thư mục đại diện bởi biến $tmp_file_location và di chuyển đến thư mục vừa tạo (đại diện bởi biến $base_location cộng với giá trị hiện tại của $today).
Cùng lúc đó, đặt tên mới là chuỗi "email" theo sau số ngẫu nhiên do lệnh rand tạo. Bạn có thể cần cài trình tạo số ngẫu nhiên: trên Ubuntu là apt install rand.
Phiên bản script trước tạo tên phân biệt bằng số thứ tự ngắn hơn, tăng dần dùng logic count=1...count=$((count+1)) trong vòng lặp for. Đó ổn miễn là không nhận nhiều batch tin nhắn cùng ngày. Nếu có, tin nhắn mới sẽ ghi đè file cũ trong thư mục ngày đó.
Tôi đoán có khả năng toán học lệnh rand gán số trùng lặp cho hai file, nhưng với phạm vi mặc định rand dùng từ 1 đến 32,576, đó là rủi ro tôi chấp nhận.
Lúc này, nên có file trong thư mục mới với tên như email3039, email25343, v.v. cho từng tin nhắn mới.
Chạy lệnh tree trên hệ thống của tôi cho thấy năm tin nhắn lưu trong thư mục 02_27_2020, và một tin nhắn nữa trong 02_28_2020 (file này tạo bằng phiên bản script cũ, nên đánh số thứ tự).
Hiện không có file trong tmpemails - vì lệnh mv di chuyển file đến vị trí mới, không để lại gì.
$ tree . ├── emails │ ├── 02_27_2020 │ │ ├── email1 │ │ ├── email2 │ │ ├── email3 │ │ ├── email4 │ │ └── email5 │ └── 02_28_2020 │ └── email1 └── tmpemailsPhần cuối script mở từng tin nhắn mới trong trình soạn thảo desktop ưa thích (Gedit). Dùng vòng lặp for...do...done tương tự, lần này đọc tên từng file trong thư mục mới (tham chiếu bằng lệnh "today") và mở file trong Gedit. Chú ý dấu hoa thị thêm ở cuối đường dẫn thư mục.
for NEWFILE in ${base_location}/${today}/* do gedit $NEWFILE doneCòn một việc nữa. Nếu không dọn S3 bucket, mỗi lần chạy script sẽ tải tất cả tin nhắn tích lũy. Sẽ càng khó quản lý.
Vì vậy, sau khi tải thành công tin nhắn mới, tôi chạy script ngắn xóa tất cả file trong bucket:
#!/bin/bash # Delete all existing emails aws s3 rm --recursive s3://bucket-name/ --profile myaccount