インターネットの発展と普及により、電子メールは人々の生活に欠かせないものになりました。この記事では、golang プログラミング言語を使用して簡単なメール サーバーを実装する方法を紹介します。
1. 環境セットアップ
まず、ローカルに golang 開発環境をセットアップする必要があります。 golang をインストールした後、GOPATH を設定する必要があります。この環境変数は golang の作業ディレクトリを指定します。このディレクトリに作成されたすべてのファイルは golang のソース コードとみなされます。
次に、次のコマンドを使用して、POP3 ライブラリと SMTP ライブラリをインストールします。
go get github.com/jordan-wright/email go get github.com/beego/mux
上記 2 つのライブラリは、それぞれ電子メールの送信と HTTP リクエストの処理に使用されます。
2. POP3 サーバーの実装
POP3 はメール受信プロトコルであり、POP3 プロトコルを使用してメールサーバーからメールをダウンロードできます。 POP3 サーバーを実装するには、TCP サーバーを golang で記述する必要があります。 golang では、「net」パッケージを使用して TCP サーバー開発を実装できます。
次は簡単な POP3 サーバー コードです:
package main import ( "bufio" "fmt" "net" "strings" ) func handlePOP3(conn net.Conn) { fmt.Fprintf(conn, "+OK POP3 ready\r\n") scanner := bufio.NewScanner(conn) for scanner.Scan() { command := scanner.Text() if strings.HasPrefix(command, "QUIT") { fmt.Fprintf(conn, "+OK Bye\r\n") conn.Close() return } fmt.Fprintf(conn, "-ERR unknown command\r\n") } } func main() { listener, err := net.Listen("tcp", ":110") if err != nil { fmt.Println("Error listening:", err.Error()) return } defer listener.Close() fmt.Println("Listening on :110") for { conn, err := listener.Accept() if err != nil { fmt.Println("Error accepting connection:", err.Error()) return } go handlePOP3(conn) } }
上記のコードはポート 110 (POP3 のデフォルト ポート) をローカルでリッスンします。クライアントが接続すると、接続を処理するために goroutine が開始されます。 。 POP3 サーバーが受信するコマンドはすべて文字列であるため、bufio パッケージが提供するスキャナーを使用してコマンドを解析します。
handlePOP3 関数では、まず「OK POP3 Ready」をクライアントに送信して、サーバーの準備ができていることを示します。その後、クライアントから送信されたコマンドをループで読み取り続け、「QUIT」コマンドに遭遇すると、「OK Bye」を送信してセッションを終了し、接続を閉じます。別の不明なコマンドを受信した場合は、「-ERR 不明なコマンド」を送信して、コマンドが無効であることをクライアントに伝えます。
3. SMTP サーバーの実装
SMTP はメール送信プロトコルであり、SMTP プロトコルを使用してメールサーバーにメールを送信できます。 SMTP サーバーを実装するには、POP3 サーバーに基づいて SMTP コマンドを処理するコードを追加する必要があります。
次は単純な SMTP サーバー コードです:
package main import ( "fmt" "net" "net/mail" "net/smtp" ) func handlePOP3(conn net.Conn) { // ... } func handleSMTP(conn net.Conn) { fmt.Fprintf(conn, "220 localhost SMTP Ready\r\n") state := 0 var from, to, data string for { buf := make([]byte, 1024) _, err := conn.Read(buf) if err != nil { fmt.Println("Error reading:", err.Error()) return } line := string(buf) switch state { case 0: if line[:4] != "HELO" { fmt.Fprintf(conn, "500 Error: bad command sequence\r\n") continue } fmt.Fprintf(conn, "250 localhost\r\n") state = 1 case 1: if line[:4] != "MAIL" { fmt.Fprintf(conn, "500 Error: bad command sequence\r\n") continue } from = line[5 : len(line)-2] fmt.Fprintf(conn, "250 OK\r\n") state = 2 case 2: if line[:4] != "RCPT" { fmt.Fprintf(conn, "500 Error: bad command sequence\r\n") continue } to = line[5 : len(line)-2] fmt.Fprintf(conn, "250 OK\r\n") state = 3 case 3: if line[:4] == "DATA" { fmt.Fprintf(conn, "354 End data with <CR><LF>.<CR><LF>\r\n") state = 4 } else if line[:4] == "HELO" { fmt.Fprintf(conn, "250 localhost\r\n") } else { fmt.Fprintf(conn, "500 Error: bad command sequence\r\n") } case 4: if line[:3] == "QUIT" { fmt.Fprintf(conn, "221 Bye\r\n") conn.Close() return } if line == ".\r\n" { fmt.Fprintf(conn, "250 OK: message accepted\r\n") msg, _ := mail.ReadMessage(strings.NewReader(data)) smtp.SendMail("localhost:25", nil, "test@test.com", []string{to}, []byte(data)) state = 1 } else { data += line } } } } func main() { // ... router := mux.NewRouter() router.HandleFunc("/pop3", handlePOP3) router.HandleFunc("/smtp", handleSMTP) http.ListenAndServe(":8080", router) }
上記のコードは、ポート 25 (SMTP のデフォルト ポート) でローカルにリッスンします。クライアントが接続すると、接続を処理するために goroutine が開始されます。 。 SMTP サーバーが受信するすべてのコマンドも文字列であるため、net パッケージによって提供される Conn.Read メソッドを使用してコマンドを読み取ります。
handleSMTP 関数では、最初に「220 localhost SMTP Ready」をクライアントに送信して、SMTP サーバーの準備ができていることを示します。次に、メール送信プロセスを処理するステート マシンを維持します。
に移行します。無効なコマンドを受信した場合は、「500 エラー: 不正なコマンド シーケンス」を送信して、コマンドが無効であることをクライアントに伝えます。 QUIT コマンドを受信すると、セッションの終了を示す「221 Bye」が送信され、接続が閉じられます。状態 4 では、net/mail パッケージを使用して電子メール データを解析し、net/smtp パッケージを使用して電子メールを送信します。
4. テスト
上記のコードを使用して実装されたメールボックス サーバーは単なる例であり、実際の運用環境で使用する場合は、多くの側面のテストと最適化が必要です。以下は、Python で書かれた単純な SMTP クライアント コードです。このクライアントを使用して、SMTP サーバーに電子メールを送信し、SMTP サーバーが適切に動作しているかどうかをテストできます:
import smtplib server = smtplib.SMTP('localhost', 25) server.ehlo() server.mail('test@test.com') server.rcpt('test1@test.com') server.data('Subject: Test Mail\n\nThis is a test email.\n') server.quit()
5。この記事の概要 golang プログラミング言語を使用して簡単な電子メール サーバーを実装する方法を学びます。 golang を使用して SMTP/POP3 サーバー コードを記述することは、理解と拡張が容易であると同時に、golang のコルーチン機能は高い同時実行性をサポートできるため、ネットワーク プログラミングの開発作業に非常に適しています。
以上がgolangを使って簡単なメールサーバーを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。