Sieve 篩選器撰寫教學

本章節是 Sieve 的程式撰寫教學,讓您瞭解如何撰寫 Sieve 的規則,但若您是尚未有經驗的初學者,請先參考 開始使用 Sieve 篩選器章節

本教學涵蓋內容

本章節將帶領您一一走過使用程式碼編寫 Sieve 篩選器的過程,您將會學到一些基本的概念,也會學到如何建立以下的篩選器:

  • 拒絕超過大小限制的郵件

  • 將群組郵件歸類到特定的資料夾中

  • 將有可疑主題或疑似垃圾信的郵件歸類到垃圾信(Junk)資料夾中

Sieve 能夠設定很多篩選條件,但本教學僅介紹幾個基本範例,目的在於讓您瞭解 Sieve 的基礎架構,並讓您能在未來自行撰寫其他規則。若您想查看更多 Sieve 的使用方法,請前往 此頁面 查閱 Gandi 支援使用的 Sieve 擴充功能,您也能在 此頁面 找到更多篩選器的範例。

宣告要使用的擴充功能

首先,您要宣告(list)您要使用的擴充功能。

Sieve 基本上已經內建了一些功能,但仍可安裝其他擴充功能。Sieve 篩選器程式碼的第一行是 require 指令,後面是您將在篩選器中使用的擴充功能列表,本教學所涉及的篩選器範例會用到 fileinto 和 reject 擴充功能。

您的程式碼第一行需宣告:

require ["fileinto", "reject"];

您可以在 此頁面 查看 Gandi 郵件伺服器所支援使用的擴充功能。

註解

編寫程式碼時,註解(comments)是被編譯器忽略的文字或段落,因此最好使用註解來描述您的程式碼用途,以便您之後回來時,可以更容易地編輯,此外,註解還能讓您更容易與別人分享您的程式碼。

使用井字號(#)表示註解,可以將井字號後的整行內容視為註解,例如:

#This is a comment.

或者,您也可以註解特定的行或是多行,例如:

/* This is also a comment. */

/* This
* is
* a comment
* which spans multiple lines. */

本教學所建立的範例篩選器都包含註解,以便向您解釋每個步驟的用途,例如:

# 我的 Sieve 郵件篩選器

# 列出本指令稿使用的擴充功能
require ["fileinto", "reject"];

建立篩選條件

現在要來建立一個封鎖大於 2MB 的郵件之篩選器。首先,您必須告訴篩選器您要搜尋的條件,您可以使用 if 指令,但請記得要撰寫註解。使用了註解與 if 後,現在您的篩選器程式碼應該如下所示:

# 大於 2MB 的郵件會被拒收並回傳錯誤通知
if

接下來,您要告訴篩選器須要篩選郵件的什麼部份,例如寄件者信箱位址、收件者信箱位址、主旨、寄出日期等,而此處的範例是要篩選郵件的 大小(size),詳見如下 :

# 大於 2MB 的郵件會被拒收並回傳錯誤通知
if size

再來,您需要告訴篩選器如何比對您的篩選條件與郵件內容,這稱為 比較運算子(comparators) ,其以冒號(:)開頭。此處,我們將使用 :over 運算子,篩選器將會找出 超過(over) 或是大於您所限制之大小的郵件(下方範例中的 2000K 等於 2MB),詳見如下:

篩選比較運算子已經完成,現在您需告訴篩選器符合條件的郵件要執行哪些動作,請使用左大括號 { 來表示動作開始,詳見如下:

# 我的 Sieve 郵件篩選器

# 列出本指令稿使用的擴充功能
require ["fileinto", "reject"];

# 大於 2MB 的郵件會被拒收並回傳錯誤通知
if size :over 2000K {

對過濾後的郵件執行動作

在您設定好條件式後,接者請告訴過濾器需要執行什麼動作。請使用雙大括號 {} 來宣告動作,並在大括號內撰寫您要針對符合篩選條件的郵件執行之動作。

您可以同時執行很多動作,例如歸類郵件至指定的資料夾、刪除郵件、轉寄郵件等等。此處範例會針對符合篩選條件的郵件執行 拒絕 之動作,詳見如下:

# 大於 2MB 的郵件會被拒收並回傳錯誤通知
if size :over 2000K {
  reject

您可以在 reject 後方加入錯誤訊息,如此一來,寄件者會收到此錯誤訊息,而最後應以分號(;)作為該行的結束。

小訣竅

欲執行之動作的程式碼每一行都應以分號作結,千萬別忘了在最後加上分號!

# 大於 2MB 的郵件會被拒收並回傳錯誤通知
if size :over 2000K {
  reject "I am unable to accept email larger than 2MB.";

在加入要執行的所有動作之後,再以一個右大括號(})作為動作的結束,到目前為止,您的程式碼應該如下所示:

# 我的 Sieve 郵件篩選器

# 列出本指令稿使用的擴充功能
require ["fileinto", "reject"];

# 大於 2MB 的郵件會被拒收並回傳錯誤通知
if size :over 2000K {
 reject "I am unable to accept email larger than 2MB.";
}

到此為止,您已經建立了一個完整的篩選器!您可以稍歇一會,但還有很多篩選條件可以練習,讓我們繼續加油!

增加其他篩選條件

您可能有很多不同類的郵件想要建立不同的篩選器,若要增加不同的篩選條件,您可以使用 elsif,這是「else if」的縮寫,讓篩選器知道若不符合第一個條件式的話,則將比對第二個條件式。

警告

撰寫 Sieve 程式碼時,必須將 所有 篩選器都放在 同一個 檔案內。當您上傳新的 Sieve 程式碼檔案到郵件伺服器上時,系統將會自動覆蓋舊的檔案,也就是說,您不需要建立新的檔案來編寫新的篩選器,否則舊的篩選器檔案會消失。

我們要建立的下一個條件式是將來自某個郵寄名單(mailing list)的信件全部歸類到一個資料夾,請使用 elsif 開始撰寫:

# 來自郵寄名單的郵件將被歸類放進 mailinglist 資料夾
elsif

篩選器會檢查郵件中的 位址 (address) 部份,因為您要找出完全符合某個位址的郵件,所以您需要使用 :is 運算子,詳見如下:

# 來自郵寄名單的郵件將被歸類放進 mailinglist 資料夾
elsif address :is

現在您已經指定了要與郵件的哪個部份比對,再來您需要編寫比對的條件,此篩選器將會比對收件者(to)和寄件者(from)的信箱位址,若其中任何一個是 mailinglist@example.com 位址,則將執行這些動作。請使用中括號([ ])編寫,並輸入要比對的信箱位址,詳見如下:

# 來自郵寄名單的郵件將被歸類放進 mailinglist 資料夾
elsif address :is ["From", "To"] "mailinglist@example.com"

接下來,請用左大括號({)來標示動作的開始,現在程式碼應如下所示:

# 我的 Sieve 郵件篩選器

# 列出本指令稿使用的擴充功能
require ["fileinto", "reject"];

# 大於 2MB 的郵件會被拒收並回傳錯誤通知
if size :over 2000K {
 reject "I am unable to accept email larger than 2MB.";
}

# 來自郵寄名單的郵件將被歸類放進 mailinglist 資料夾
elsif address :is ["From", "To"] "mailinglist@example.com" {

將指定的郵件歸類到指定資料夾

Sieve 篩選器最常見的用途之一是將特定的郵件歸類到資料夾中,您可以使用 fileinto 指令將郵件歸類至指定的資料夾。

此處範例的篩選器會將寄給(或來自) mailinglist@example.com 的郵件歸類到名為 mailinglist 的資料夾中,該資料夾位於收件夾(inbox)內,所以您需要使用 INBOX/mailinglist 的方式來指定路徑,詳見如下:

# 來自郵寄名單的郵件將被歸類放進 mailinglist 資料夾
elsif address :is ["From", "To"] "mailinglist@example.com" {
  fileinto "INBOX/mailinglist";
}

目前您的篩選器應如下所示:

# 我的 Sieve 郵件篩選器

# 列出本指令稿使用的擴充功能
require ["fileinto", "reject"];

# 大於 2MB 的郵件會被拒收並回傳錯誤通知
if size :over 2000K {
 reject "I am unable to accept email larger than 2MB.";
}

# 來自郵寄名單的郵件將被歸類放進 mailinglist 資料夾
elsif address :is ["From", "To"] "mailinglist@example.com" {
  fileinto "INBOX/mailinglist";
}

同時比對多個條件

若要同時比對多個條件,您可以使用 anyofallof 指令。anyof 表示只要符合一個條件,就會執行動作;allof 則表示要同時符合所有條件才會執行動作。以下範例使用 anyof 來設定只要符合一個條件就會執行動作,詳見如下:

# 如果郵件並非直接發送給我,或者是郵件主旨包含「free money」或「Nigerian
# prince」字眼,該郵件會被放進垃圾信資料夾。
elsif anyof

然後,您需要將條件放到括號內,而且不同的條件需用逗號分隔。第一個條件式是找出不是發送給您(例如您的信箱位址是 myemailaddress@gmail.com)的郵件。要撰寫一個「否定」的條件式(亦即找出不是寄給您的郵件)需要在條件式的開頭加上 not,但是許多電子郵件是發送給一個以上的信箱位址,因此,此篩選器需使用 :contains 來找出符合收件者(to)、副本(cc)或密件副本(bcc)的信箱位址。

# 如果郵件並非直接發送給我,或者是郵件主旨包含「free money」或「Nigerian
# prince」字眼,該郵件會被放進垃圾信資料夾。
elsif anyof (not address :all :contains ["To", "Cc", "Bcc"] "myemailaddress@example.com",

下一個條件式是查看主旨中是否出現一些關鍵字,現在您必須使用 :matches 運算子來查找。:matches 運算子與 :contains 運算子非常類似,但前者可以使用萬用字元。萬用字元 * 意思為任何字元,例如 *free money* 表示找尋任何擁有「free money」字眼的字串,詳見如下:

header :matches "Subject" ["*free money*","*Nigerian prince*"]

當您將兩個條件式都寫入後,篩選器程式碼應如下所示:

# 如果郵件並非直接發送給我,或者是郵件主旨包含「free money」或「Nigerian
# prince」字眼,該郵件會被放進垃圾信資料夾。
elsif anyof (not address :all :contains ["To", "Cc", "Bcc"] "myemailaddress@example.com",
header :matches "Subject" ["*free money*","*Nigerian prince*"]) {

最後,我們要再次使用 fileinto 指令來將符合篩選條件的郵件歸類到垃圾信資料夾,此時,您的程式碼應如下所示:

# 我的 Sieve 郵件篩選器

# 列出本指令稿使用的擴充功能
require ["fileinto", "reject"];

# 大於 2MB 的郵件會被拒收並回傳錯誤通知
if size :over 2000K {
  reject "I am unable to accept email larger than 2MB.";
}

# 來自郵寄名單的郵件將被歸類放進 mailinglist 資料夾
elsif address :is ["From", "To"] "mailinglist@example.com" {
  fileinto "INBOX/mailinglist";
}

# 如果郵件並非直接發送給我,或者是郵件主旨包含「free money」或「Nigerian
# prince」字眼,該郵件會被放進垃圾信資料夾。
elsif anyof (not address :all :contains ["To", "Cc", "Bcc"] "myemailaddress@example.com",
header :matches "Subject" ["*free money*","*Nigerian prince*"]) {
  fileinto "INBOX/spam";
}

將其他信件都歸類到特定資料夾

最後的範例我們將建立一個篩選器,將所有不符合上述條件的電子郵件都歸類到名為 to sort 的資料夾內。注意!這不是撰寫 Sieve 篩選器的必要設定,Sieve 預設任何未被篩選的郵件都會回歸到收件夾中。然而,此處的範例只是示範如何將剩下的郵件歸類到一個特定的資料夾(如果您希望這樣做),詳見如下:

# 將剩下所有新收到的郵件放進一個資料夾,待之後再歸檔。
else {
  fileinto "INBOX/tosort";
}

加上最後的指令後,所有的篩選器便撰寫完成:

# 我的 Sieve 郵件篩選器

# 列出本指令稿使用的擴充功能
require ["fileinto", "reject"];

# 大於 2MB 的郵件會被拒收並回傳錯誤通知
if size :over 2000K {
  reject "I am unable to accept email larger than 2MB.";
}

# 來自郵寄名單的郵件將被歸類放進 mailinglist 資料夾
elsif address :is ["From", "To"] "mailinglist@example.com" {
  fileinto "INBOX/mailinglist";
}

# 如果郵件並非直接發送給我,或者是郵件主旨包含「free money」或「Nigerian
# prince」字眼,該郵件會被放進垃圾信資料夾。
elsif anyof (not address :all :contains ["To", "Cc", "Bcc"] "myemailaddress@example.com",
header :matches "Subject" ["*free money*","*Nigerian prince*"]) {
  fileinto "INBOX/spam";
}

# 將剩下所有新收到的郵件放進一個資料夾,待之後再歸檔。
else {
  fileinto "INBOX/tosort";
}

希望本章節能幫助您瞭解 Sieve 的重要元素,請注意!Sieve 非常具有彈性,因此除了上述的指令之外,還有很多其他功能。若您想進一步瞭解更多 Sieve 的指令與使用方式,請前往 此頁面 查閱 Gandi 支援使用的 Sieve 擴充功能,您也能在 此頁面 找到更多篩選器的範例 。