ホームページ >バックエンド開発 >Golang >Golang が SMTP メール転送機能を実装する方法

Golang が SMTP メール転送機能を実装する方法

PHPz
PHPzオリジナル
2023-04-25 10:33:191257ブラウズ

Golang は強力なプログラミング言語として、ネットワーク プログラミングの分野で特に優れたパフォーマンスを発揮します。ネットワーク経由で通信する場合、Golang は多くの便利なツールとライブラリを提供します。その 1 つが SMTP ライブラリです。ネットワーク伝送プロトコルとして、SMTP プロトコルは電子メールの送受信に使用され、ネットワーク通信の重要な部分です。実際のアプリケーションでは、受信したメールを転送する必要がある場合がありますが、この記事では、Golang が SMTP メール転送機能をどのように実装しているかを紹介します。

  1. SMTP の概要

SMTP (Simple Mail Transfer Protocol) は、電子メールの送受信に使用されるテキストベースのメール転送プロトコルです。 SMTP プロトコルはインターネット標準プロトコルの 1 つで、電子メール送信の中核となるプロトコルです。 SMTP プロトコルは、基礎となる送信プロトコルとして TCP を使用し、送信ポートとしてポート 25 を使用します。

SMTP には、次の基本概念が含まれています。

  • メール送信者: メールを送信する必要があるユーザーまたはシステム。
  • メール受信者: メールを受信する必要があるユーザーまたはシステム。
  • SMTP クライアント: 電子メールの送信に使用されるアプリケーション。
  • SMTP サーバー: 電子メールの受信と転送に使用されるサーバー。

SMTP プロトコルのワークフローは次のとおりです。

  • クライアントは SMTP サーバーに接続します。
  • クライアントは EHLO コマンドをサーバーに送信して、通信パラメータをネゴシエートします。
  • クライアントは認証情報をサーバーに送信します。
  • クライアントは電子メール情報と受信者情報をサーバーに送信します。
  • サーバーは受信者情報に基づいて受信サーバーを見つけて接続します。
  • 電子メール情報と受信者情報を受信サーバーに送信します。
  • 受信サーバーは、電子メールを対応するメールボックスに保存します。
  1. SMTP ライブラリの使用方法

Golang の SMTP ライブラリを使用すると、簡単にメールを送信できます。 Golang の SMTP ライブラリは、SMTP プロトコルに基づいて電子メール送信機能を実装し、便利な API インターフェイスを提供します。

まず、SMTP ライブラリに用意されている Dial 関数を使用して SMTP サーバーに接続する必要があります。この関数は、SMTP サーバーのアドレスとポート番号、ユーザー名とパスワード、その他の情報を渡す必要があります。

func Dial(addr string, a Auth) (*Client, error)

このうち、Auth タイプは、ユーザー名やパスワードなどの SMTP サーバーの認証情報を表します。 SMTP サーバーに接続するサンプル コードは次のとおりです。

import (

"net/smtp"

)

func main() {

// 创建认证信息
auth := smtp.PlainAuth("", "smtp_username", "smtp_password", "smtp_host")

// 连接SMTP服务器
client, err := smtp.Dial("smtp_host:smtp_port")
if err != nil {
    panic(err)
}

// 登录SMTP服务器
err = client.Auth(auth)
if err != nil {
    panic(err)
}

// 退出SMTP服务器
defer client.Quit()

}

接続 SMTP サーバーが成功すると、SMTP プロトコルの要件に従って電子メール情報をサーバーに送信できます。送信者と受信者の情報を送信するには、smtp ライブラリによって提供される Mail メソッドと Rcpt メソッドを使用する必要があります。 Mail メソッドと Rcpt メソッドのサンプル コードは次のとおりです。

// 送信者情報の送信
func (c *Client) Mail(from string) error

// 受信者情報の送信
func (c *Client) Rcpt(to string) error

電子メール情報を送信するには、smtp ライブラリによって提供される Data メソッドを使用して、電子メールの内容を SMTP サーバーに送信する必要があります。 Data メソッドのサンプル コードは次のとおりです。

// 電子メール コンテンツの送信
func (c *Client) Data() (io.WriteCloser, error)

送信後接続を閉じる必要がある場合は、Quit メソッドを使用して SMTP サーバーを終了します。コードは次のとおりです。

//SMTP サーバーを終了します
func (c *Client) Quit() error

  1. メール転送機能の実装

メール転送機能を実装するには、メール受信後、メール内容を指定した宛先に転送する必要があります。したがって、Golang の SMTP ライブラリを使用して、指定した SMTP サーバーと受信者に電子メールのコンテンツを送信する必要があります。

具体的な手順は次のとおりです。

  • プロジェクトのポート番号をリッスンし、受信メールを受け入れます。
  • 受信者と送信者が要件を満たしているかどうかを判断します。一致する場合、電子メールの内容はメール タイプにカプセル化され、転送サービス アドレスに送信されます。
  • 転送サービスからの応答を受信し、電子メールが正常に転送されたかどうかを判断します。

具体的な実装コードは次のとおりです。

import (

"bytes"
"errors"
"fmt"
"log"
"net"
"net/smtp"
"strings"

)

// リスニング ポート
func ListenAndServe(addr) string) error {

listener, err := net.Listen("tcp", addr)
if err != nil {
    return err
}

defer listener.Close()

for {
    conn, err := listener.Accept()
    if err != nil {
        log.Printf("Failed to accept connection (%s)", err)
        continue
    }

    go handleConnection(conn)
}

}

// 受信メールの処理
func handleConnection(conn net.Conn) {

defer conn.Close()

// 读取邮件内容
buf := make([]byte, 4096)
n, err := conn.Read(buf)
if err != nil {
    log.Printf("Failed to read connection (%s)", err)
    return
}

defer conn.Close()

// 解析邮件
message, err := parseMessage(buf[:n])
if err != nil {
    log.Printf("Failed to parse message (%s)", err)
    return
}

// 判断收件人和发件人是否符合要求
if !checkRecipient(message.Recipient) {
    log.Printf("Invalid recipient (%s)", message.Recipient)
    return
}

if !checkSender(message.Sender) {
    log.Printf("Invalid sender (%s)", message.Sender)
    return
}

// 构建SMTP客户端
auth := smtp.PlainAuth("", "smtp_username", "smtp_password", "smtp_host")
client, err := smtp.Dial("smtp_host:smtp_port")
if err != nil {
    log.Printf("Failed to connect SMTP server (%s)", err)
    return
}
defer client.Quit()

// 发送邮件内容
err = client.Mail("from_address")
if err != nil {
    log.Printf("Failed to send 'MAIL FROM' command (%s)", err)
    return
}

err = client.Rcpt(message.Recipient)
if err != nil {
    log.Printf("Failed to send 'RCPT TO' command (%s)", err)
    return
}

w, err := client.Data()

if err != nil {
    log.Printf("Failed to send 'DATA' command (%s)", err)
    return
}

defer w.Close()

buf.WriteString(fmt.Sprintf("To: %s\r\n", message.Recipient))
buf.WriteString(fmt.Sprintf("From: %s\r\n", message.Sender))
buf.WriteString(fmt.Sprintf("Subject: %s\r\n", message.Subject))
buf.WriteString("\r\n")
buf.WriteString(message.Body)

_, err = w.Write(buf.Bytes())
if err != nil {
    log.Printf("Failed to write email to client (%s)", err)
    return
}

log.Printf("Mail sent to %s", message.Recipient)

}

/ / 電子メールの内容を解析します
func parseMessage(message []byte) (*メッセージ、エラー) {

var msg Message
msg.Body = string(message)

// 提取发件人地址
start := bytes.Index(message, []byte("From: "))
if start == -1 {
    return nil, errors.New("Failed to find 'From:' in message")
}

start += 6
end := bytes.Index(message[start:], []byte("\r\n"))
if end == -1 {
    return nil, errors.New("Failed to find end of 'From:' in message")
}

msg.Sender = string(message[start : start+end])

// 提取收件人地址
start = bytes.Index(message, []byte("To: "))
if start == -1 {
    return nil, errors.New("Failed to find 'To:' in message")
}

start += 4
end = bytes.Index(message[start:], []byte("\r\n"))
if end == -1 {
    return nil, errors.New("Failed to find end of 'To:' in message")
}

msg.Recipient = string(message[start : start+end])

// 提取邮件主题
start = bytes.Index(message, []byte("Subject: "))
if start == -1 {
    return nil, errors.New("Failed to find 'Subject:' in message")
}

start += 9
end = bytes.Index(message[start:], []byte("\r\n"))
if end == -1 {
    return nil, errors.New("Failed to find end of 'Subject:' in message")
}

msg.Subject = string(message[start : start+end])

return &msg, nil

}

// 受信者が正当であるかどうかを確認します
func checkRecipient (受信者文字列) bool {

// 收件人地址必须以@mydomain.com结尾
return strings.HasSuffix(recipient, "@mydomain.com")

}

//送信者が正当であるかどうかを確認する
func checkSender(送信者文字列) bool {

// 任意发件人地址均合法
return true

}

//メール構造
type Message struct {

Sender    string
Recipient string
Subject   string
Body      string

}

  1. 結論

Golang の SMTP ライブラリを通じて、簡単に実装できます。メールの送信・転送機能。 SMTP 電子メール転送を実装する場合は、電子メール コンテンツのセキュリティを確保するために、受信者と送信者の検証に注意を払う必要があります。実際のアプリケーションでは、SMTP 電子メール転送機能は、企業内の内部電子メール転送、ソーシャル ネットワークでのメッセージ転送など、さまざまなシナリオに適用できます。

以上がGolang が SMTP メール転送機能を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。