首頁 >後端開發 >Python教學 >您的行銷電子郵件最終會成為垃圾郵件嗎?我們建立了一個工具來找出答案

您的行銷電子郵件最終會成為垃圾郵件嗎?我們建立了一個工具來找出答案

Susan Sarandon
Susan Sarandon原創
2024-12-31 09:47:10169瀏覽

開展電子郵件行銷活動時,最大的挑戰之一是確保您的郵件到達收件匣而不是垃圾郵件資料夾。

在這篇文章中,我們將建立一個工具,可以驗證您的電子郵件是否會被標記為垃圾郵件以及為什麼被標記為垃圾郵件。
該工具將以 API 形式並在線上部署,以便可以整合到您的工作流程中。

垃圾郵件驗證背後的秘密

Apache SpamAssassin 是一個由 Apache 軟體基金會維護的開源垃圾郵件偵測平台,它是許多電子郵件用戶端和電子郵件過濾工具廣泛使用的工具,用於將郵件分類為垃圾郵件。

它使用多種規則、貝葉斯過濾和網路測試來為給定的電子郵件分配垃圾郵件「分數」。一般來說,得分為 5 或以上的電子郵件被標記為垃圾郵件的風險很高。

由於 Apache SpamAssassin 是一個垃圾郵件偵測軟體,因此它也可以用來判斷您的電子郵件是否會被標記為垃圾郵件。

SpamAssassin 的評分是透明且有據可查的,您可以放心地使用它來準確識別電子郵件的哪些方面導致了高垃圾郵件分數並提高您的寫作水平。

如何使用 SpamAssassin 驗證您的電子郵件

SpamAssassin 設計為在 Linux 系統上運作。您需要 Linux 作業系統或建立 Docker 容器來安裝和執行它。

在 Debian 或 Ubuntu 系統上,使用以下指令安裝 SpamAssassin:

apt-get update && apt-get install -y spamassassin
sa-update

sa-update 指令確保 SpamAssassin 的規則是最新的。

安裝後,您可以將電子郵件訊息透過管道傳輸到 SpamAssassin 的命令列工具中。輸出包括帶有垃圾郵件分數的電子郵件的註釋版本,並解釋了觸發哪些規則。

典型用法可能如下圖所示:

spamassassin -t < input_email.txt > results.txt

results.txt 將包含處理後的電子郵件以及 SpamAssassin 的標頭和分數,如下所示:

X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on 254.254.254.254
X-Spam-Level: 
X-Spam-Status: No, score=0.2 required=5.0 tests=HTML_MESSAGE,
    MIME_HTML_ONLY,MISSING_MID,NO_RECEIVED,
    NO_RELAYS autolearn=no autolearn_force=no version=4.0.0

// ...

Content analysis details:   (0.2 points, 5.0 required)

 pts rule name              description
---- ---------------------- --------------------------------------------------
 0.1 MISSING_MID            Missing Message-Id: header
-0.0 NO_RECEIVED            Informational: message has no Received headers
-0.0 NO_RELAYS              Informational: message was not relayed via SMTP
 0.0 HTML_MESSAGE           BODY: HTML included in message
 0.1 MIME_HTML_ONLY         BODY: Message only has text/html MIME parts

將 SpamAssassin 包裝為 API

SpamAssassin 只有在封裝為 API 時才能發揮其最大潛力,因為這種形式使其更加靈活並允許整合到各種工作流程中。

想像一下:在您點擊電子郵件上的「發送」之前,內容首先發送到 SpamAssassin API。僅當確定電子郵件不符合垃圾郵件標準時才允許繼續。

讓我們建立一個簡單的 API 來接受這些電子郵件欄位:主題、html_body 和 text_body。它將把欄位傳遞給 SpamAssassin 並傳回驗證結果。

API範例

from fastapi import FastAPI
from datetime import datetime, timezone
from email.utils import format_datetime
from pydantic import BaseModel
import subprocess

def extract_analysis_details(text):
    lines = text.splitlines()

    start_index = None
    for i, line in enumerate(lines):
        if line.strip().startswith("pts rule"):
            start_index = i
            break

    if start_index is None:
        print("No content analysis details found.")
        return []

    data_lines = lines[start_index+2:]
    parsed_lines = []
    for line in data_lines:
        if line.strip() == "":
            break
        parsed_lines.append(line)

    results = []
    current_entry = None

    split_line = lines[start_index+1]
    pts_split, rule_split, *rest = split_line.strip().split(" ")

    pts_start = 0
    pts_end = pts_start + len(pts_split)

    rule_start = pts_end + 1
    rule_end = rule_start + len(rule_split)

    desc_start = rule_end + 1

    for line in parsed_lines:
        pts_str = line[pts_start:pts_end].strip()
        rule_name_str = line[rule_start:rule_end].strip()
        description_str = line[desc_start:].strip()

        if pts_str == "" and rule_name_str == "" and description_str:
            if current_entry:
                current_entry["description"] += " " + description_str
        else:
            current_entry = {
                "pts": pts_str,
                "rule_name": rule_name_str,
                "description": description_str
            }
            results.append(current_entry)

    return results

app = FastAPI()

class Email(BaseModel):
    subject: str
    html_body: str
    text_body: str

@app.post("/spam_check")
def spam_check(email: Email):
    # assemble the full email
    message = f"""From: example@example.com
To: recipient@example.com
Subject: {email.subject}
Date: {format_datetime(datetime.now(timezone.utc))}
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="__SPAM_ASSASSIN_BOUNDARY__"

--__SPAM_ASSASSIN_BOUNDARY__
Content-Type: text/plain; charset="utf-8"

{email.text_body}

--__SPAM_ASSASSIN_BOUNDARY__
Content-Type: text/html; charset="utf-8"

{email.html_body}

--__SPAM_ASSASSIN_BOUNDARY__--"""

    # Run SpamAssassin and capture the output directly
    output = subprocess.run(["spamassassin", "-t"],
                            input=message.encode('utf-8'),
                            capture_output=True)

    output_str = output.stdout.decode('utf-8', errors='replace')
    details = extract_analysis_details(output_str)
    return {"result": details}

在上面的程式碼中,我們定義了一個輔助函數 extract_analysis_details,用於從完整結果報告中僅提取評分原因。您可以進一步改進此功能,例如從結果中過濾掉某些規則。

回覆將包含 SpamAssassin 結果的分析詳細資訊。

讓我們以此輸入為例:

主題

apt-get update && apt-get install -y spamassassin
sa-update

html_body

spamassassin -t < input_email.txt > results.txt

text_body

X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on 254.254.254.254
X-Spam-Level: 
X-Spam-Status: No, score=0.2 required=5.0 tests=HTML_MESSAGE,
    MIME_HTML_ONLY,MISSING_MID,NO_RECEIVED,
    NO_RELAYS autolearn=no autolearn_force=no version=4.0.0

// ...

Content analysis details:   (0.2 points, 5.0 required)

 pts rule name              description
---- ---------------------- --------------------------------------------------
 0.1 MISSING_MID            Missing Message-Id: header
-0.0 NO_RECEIVED            Informational: message has no Received headers
-0.0 NO_RELAYS              Informational: message was not relayed via SMTP
 0.0 HTML_MESSAGE           BODY: HTML included in message
 0.1 MIME_HTML_ONLY         BODY: Message only has text/html MIME parts

回應將是這樣的:

from fastapi import FastAPI
from datetime import datetime, timezone
from email.utils import format_datetime
from pydantic import BaseModel
import subprocess

def extract_analysis_details(text):
    lines = text.splitlines()

    start_index = None
    for i, line in enumerate(lines):
        if line.strip().startswith("pts rule"):
            start_index = i
            break

    if start_index is None:
        print("No content analysis details found.")
        return []

    data_lines = lines[start_index+2:]
    parsed_lines = []
    for line in data_lines:
        if line.strip() == "":
            break
        parsed_lines.append(line)

    results = []
    current_entry = None

    split_line = lines[start_index+1]
    pts_split, rule_split, *rest = split_line.strip().split(" ")

    pts_start = 0
    pts_end = pts_start + len(pts_split)

    rule_start = pts_end + 1
    rule_end = rule_start + len(rule_split)

    desc_start = rule_end + 1

    for line in parsed_lines:
        pts_str = line[pts_start:pts_end].strip()
        rule_name_str = line[rule_start:rule_end].strip()
        description_str = line[desc_start:].strip()

        if pts_str == "" and rule_name_str == "" and description_str:
            if current_entry:
                current_entry["description"] += " " + description_str
        else:
            current_entry = {
                "pts": pts_str,
                "rule_name": rule_name_str,
                "description": description_str
            }
            results.append(current_entry)

    return results

app = FastAPI()

class Email(BaseModel):
    subject: str
    html_body: str
    text_body: str

@app.post("/spam_check")
def spam_check(email: Email):
    # assemble the full email
    message = f"""From: example@example.com
To: recipient@example.com
Subject: {email.subject}
Date: {format_datetime(datetime.now(timezone.utc))}
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="__SPAM_ASSASSIN_BOUNDARY__"

--__SPAM_ASSASSIN_BOUNDARY__
Content-Type: text/plain; charset="utf-8"

{email.text_body}

--__SPAM_ASSASSIN_BOUNDARY__
Content-Type: text/html; charset="utf-8"

{email.html_body}

--__SPAM_ASSASSIN_BOUNDARY__--"""

    # Run SpamAssassin and capture the output directly
    output = subprocess.run(["spamassassin", "-t"],
                            input=message.encode('utf-8'),
                            capture_output=True)

    output_str = output.stdout.decode('utf-8', errors='replace')
    details = extract_analysis_details(output_str)
    return {"result": details}

看到了嗎? 「親愛的獲獎者」被偵測到,因為它常用於垃圾郵件。

線上部署API

運行SpamAssassin需要安裝了該軟體的Linux環境。傳統上,您可能需要 EC2 執行個體或 DigitalOcean Droplet 進行部署,這可能成本高昂且乏味,特別是在您的使用量較低的情況下。

對於無伺服器平台,他們只是不允許你安裝任何系統軟體包,例如 SpamAssassin。

Leapcell 可以完美地勝任這項工作。

使用 Leapcell,您可以部署像 SpamAssassin 一樣的任何系統包,同時保持服務無伺服器 - 您只需為呼叫付費,這通常更便宜。

在 Leapcell 上部署 API 非常簡單。您不必設定任何環境。只需部署一個Python鏡像,並正確填寫“Build Command”欄位​​即可。

Will Your Marketing Email End Up in Spam? We Built a Tool to Find Out

部署後,您將擁有一個用於垃圾郵件驗證的 API。每當呼叫 API 時,它都會執行 SpamAssassin,對電子郵件進行評分並傳回分數。

Will Your Marketing Email End Up in Spam? We Built a Tool to Find Out

閱讀我們的部落格

以上是您的行銷電子郵件最終會成為垃圾郵件嗎?我們建立了一個工具來找出答案的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn