tencent cloud

Go 호출 예시

Download
포커스 모드
폰트 크기
마지막 업데이트 시간: 2026-05-12 16:00:22
다음은 SMTP를 사용하여 Go 언어(v1.16)로 이메일을 보내는 예시 코드입니다.

// 사용하여 이메일을 전송하는 Go 언어 예제를 제공합니다.
//
// 이 코드는 SMTP 프로토콜(포트 465, SSL/TLS 암호화)을 통해 Tencent Cloud SES
// 에 이메일 전송 요청을 보내는 방법을 보여줍니다. 전체 흐름은 다음 단계로 구성됩니다:
// 1. 전송 파라미터(발신자, 수신자, Cc, Bcc, 제목, 본문 등) 준비;
// 2. RFC 822 형식으로 이메일 Header와 Body 구성 (Body는 Base64로 인코딩);
// 3. tls.Dial을 사용하여 SMTP 서버에 암호화된 연결 설정;
// 4. PlainAuth를 통해 인증 완료;
// 5. MAIL FROM, RCPT TO, DATA 등의 SMTP 명령을 순차적으로 실행하여 메시지 전송.
//
// 이 코드를 사용하기 전에 Tencent Cloud Email Push 콘솔에서 다음 준비 작업을 완료하세요:
// - 발신 도메인(Sender Domain) 생성 및 검증;
// - 발신 주소(Sender Address) 생성 및 SMTP 전송 활성화;
// - 콘솔의 "SMTP 비밀번호" 메뉴에서 전용 비밀번호 생성
// (참고: Tencent Cloud 계정 비밀번호가 아닙니다);
// - 발신 주소에 사용 가능한 전송 할당량이 있는지 확인.
//
// 의존성: 표준 라이브러리 net/smtp 및 crypto/tls만 사용하며, 외부 패키지가 필요하지 않습니다.
//
// 이 파일은 //go:build ignore 빌드 태그를 사용하여 동일한 디렉터리에 다른 데모 파일이
// 있을 때 기본 빌드에서 제외되도록 합니다.
// 이 단일 예제를 실행하려면: go run smtp-go-demo.ko.go
package main

import (
"crypto/tls"
"encoding/base64"
"fmt"
"log"
"net"
"net/smtp"
)

// Test465 는 포트 465 (SSL/TLS)를 통해 HTML 형식의 이메일을 전송하는 예제입니다.
//
// 작업 흐름:
// 1. SMTP 서버 주소, 포트, 발신 계정 및 SMTP 비밀번호 설정;
// 2. 이메일 헤더 (From / To / Cc / Bcc / Subject / Content-Type 등) 구성;
// 3. 본문을 Base64로 인코딩하여 헤더 뒤에 추가
// (헤더와 본문 사이에 빈 줄이 필요);
// 4. smtp.PlainAuth를 사용하여 PLAIN 인증 객체 생성;
// 5. SendMailWithTLS를 호출하여 TLS 연결을 통해 메시지 전송.
//
// 반환값: 성공 시 nil 반환, 실패 시 구체적인 오류 반환.
func Test465() error {
// SMTP 서버 주소. Tencent Cloud Email Push의 경우 smtp.qcloudmail.com 으로 고정.
host := "smtp.qcloudmail.com"
// SMTP 포트: 465는 SSL/TLS 암호화 연결을 의미합니다;
// STARTTLS를 사용하려면 포트 25로 변경하고, 코드의 tls.Dial도
// 그에 맞게 net.Dial + StartTLS로 변경해야 합니다.
port := 465

// email: 콘솔에서 생성 및 검증된 발신 주소(Sender Address);
// SMTP 비밀번호를 소유한 계정과 일치해야 합니다.
email := "abc@cd.com"
// password: 콘솔의 "SMTP 설정" 페이지에서 이 발신 주소를 위해
// 별도로 생성된 SMTP 비밀번호.
// Tencent Cloud 로그인 비밀번호도 API 키도 아닙니다.
password := "****"

// 수신자 주소 (필수, 최소 한 개)
toEmail := "test@test123.com"
// 참조(Cc) 주소 (선택)
ccEmail := "cc@test123.com"
// 숨은참조(Bcc) 주소 (선택)
bccEmail := "bcc@test123.com"

// 이메일 헤더를 구성합니다. SMTP 프로토콜은 헤더 필드를 "Key: Value\\r\\n"
// 형식으로 작성하도록 요구하며, 모든 헤더 뒤에는 빈 줄("\\r\\n")이 필요하고,
// 그 뒤에 본문이 따라옵니다.
header := make(map[string]string)
// "From"은 "표시 이름 <발신 주소>" 형식으로 작성하는 것이 권장됩니다.
// 표시 이름은 받은 편지함에서 발신자 별칭으로 표시됩니다.
header["From"] = "test " + "<" + email + ">"
header["To"] = toEmail
header["Cc"] = ccEmail
header["Bcc"] = bccEmail
// 이메일 제목. 비 ASCII 문자가 포함된 경우 RFC 2047 인코딩
// (=?UTF-8?B?...?=)이 권장됩니다. 이 예제는 순수 ASCII이므로 인코딩이 적용되지 않았습니다.
header["Subject"] = "test subject"

// Content-Type은 본문이 HTML임을 지정하고 문자셋을 UTF-8로 선언합니다.
header["Content-Type"] = "text/html; charset=UTF-8"
// Content-Transfer-Encoding은 본문의 전송 인코딩을 지정합니다.
// base64를 사용하면 비 ASCII 또는 특수 문자가 SMTP 전송 중에
// 잘리거나 손상되는 것을 방지할 수 있습니다.
header["Content-Transfer-Encoding"] = "base64"

// HTML 본문 샘플
body := "<!DOCTYPE html>\\n<html>\\n<head>\\n<meta charset=\\"utf-8\\">\\n<title>hello world</title>\\n</head>\\n<body>\\n " +
"<h1>나의 첫 번째 제목</h1>\\n <p>나의 첫 번째 단락입니다.</p>\\n</body>\\n</html>"

// 일반 텍스트 이메일을 보내려면 위의 HTML 구성을 주석 처리하고
// 다음 두 줄을 활성화하세요:
//header["Content-Type"] = "text/plain; charset=UTF-8"
//body := "test body"

// 최종 SMTP 메시지를 구성합니다: 먼저 모든 헤더를 "Key: Value\\r\\n"으로
// 연결하고, 구분자로 빈 줄을 추가한 다음, 마지막으로 Base64로 인코딩된
// 본문을 덧붙입니다.
message := ""
for k, v := range header {
message += fmt.Sprintf("%s: %s\\r\\n", k, v)
}
message += "\\r\\n" + base64.StdEncoding.EncodeToString([]byte(body))

// PLAIN 인증 객체를 생성합니다.
// 1번째 매개변수 "identity"는 보통 비어 있고, 2번째는 사용자 이름
// (발신 주소), 3번째는 SMTP 비밀번호, 4번째는 host (서버 측 검증에 사용)입니다.
auth := smtp.PlainAuth(
"",
email,
password,
host,
)

// TLS 버전의 전송 함수를 호출하여 서버 주소, 인증 객체, 발신자,
// 수신자 목록 및 원시 메시지를 전달합니다.
// 참고: "to" 목록은 SMTP의 RCPT TO 명령에 사용되며 실제로 어떤 메일함이
// 이메일을 받을지 결정합니다. Cc/Bcc 수신자도 실제로 메시지를 받게 하려면
// ccEmail / bccEmail도 이 목록에 추가해야 합니다.
err := SendMailWithTLS(
fmt.Sprintf("%s:%d", host, port),
auth,
email,
[]string{toEmail},
[]byte(message),
)
if err != nil {
fmt.Println("Send email error:", err)
} else {
fmt.Println("Send mail success!")
}
return err
}

// Dial 은 SMTP 서버에 TLS 암호화 연결을 설정하고 사용 가능한
// *smtp.Client 를 반환합니다.
//
// 매개변수:
// - addr: "host:port" 형식의 서버 주소, 예: "smtp.qcloudmail.com:465".
//
// 참고:
// - 표준 라이브러리의 smtp.Dial은 기본적으로 일반(plain) 연결을 사용합니다.
// 포트 465의 경우, 먼저 TLS 채널을 설정한 다음 SMTP 클라이언트로 래핑해야 하므로,
// 이 함수는 net.Dial 대신 tls.Dial을 사용합니다.
// - 두 번째 인자는 *tls.Config이며, nil을 전달하면 기본 구성
// (서버 인증서를 검증함)을 사용한다는 의미입니다.
// 인증서 검증을 건너뛰려면(프로덕션 사용은 권장하지 않음),
// &tls.Config{InsecureSkipVerify: true}를 전달하세요.
func Dial(addr string) (*smtp.Client, error) {
conn, err := tls.Dial("tcp", addr, nil)
if err != nil {
log.Println("tls.Dial Error:", err)
return nil, err
}

// smtp.NewClient는 EHLO/HELO 핸드셰이크를 위해 host (포트 제외)가 필요합니다.
host, _, _ := net.SplitHostPort(addr)
return smtp.NewClient(conn, host)
}

// SendMailWithTLS 는 TLS 암호화된 SMTP 연결을 통해 완전한 이메일 전송을 수행합니다.
//
// 매개변수:
// - addr: "host:port" 형식의 SMTP 서버 주소.
// - auth: SMTP 인증 객체. smtp.PlainAuth로 생성 가능;
// 인증이 필요하지 않으면 nil을 전달합니다.
// - from: MAIL FROM 명령에서 사용되는 발신자 주소.
// 인증된 계정과 일치해야 합니다.
// - to: RCPT TO 명령에서 사용되는 수신자 목록.
// To, Cc, Bcc의 모든 실제 수신자를 포함합니다.
// - msg: 완전한 이메일 메시지 (Header + 빈 줄 + Body), RFC 822 형식이어야 합니다.
//
// 단계:
// 1. Dial을 통해 TLS + SMTP 연결 설정;
// 2. 서버가 AUTH 확장을 지원하는 경우 인증 수행;
// 3. MAIL FROM, RCPT TO, DATA 명령을 순차적으로 실행;
// 4. 이메일 본문을 작성하고 데이터 스트림을 닫음;
// 5. QUIT 명령을 호출하여 세션을 정상적으로 종료.
//
// 어떤 단계라도 실패하면 즉시 해당 오류를 반환합니다.
func SendMailWithTLS(addr string, auth smtp.Auth, from string,
to []string, msg []byte) (err error) {
// 1. TLS 연결을 설정하고 SMTP 클라이언트를 얻습니다.
c, err := Dial(addr)
if err != nil {
log.Println("Create smtp client error:", err)
return err
}
// 연결 누수를 피하기 위해 연결이 최종적으로 닫히도록 보장합니다.
defer c.Close()

// 2. auth가 제공되고 서버가 EHLO를 통해 AUTH 확장을 알리는 경우,
// 인증을 수행합니다.
if auth != nil {
if ok, _ := c.Extension("AUTH"); ok {
if err = c.Auth(auth); err != nil {
log.Println("Error during AUTH", err)
return err
}
}
}

// 3. MAIL FROM 명령을 보내 서버에게 발신자가 누구인지 알립니다.
if err = c.Mail(from); err != nil {
return err
}
// 4. 각 수신자에 대해 RCPT TO 명령을 보냅니다.
for _, addr := range to {
if err = c.Rcpt(addr); err != nil {
return err
}
}

// 5. DATA 명령을 보내고 이메일 콘텐츠 (Header + Body)를 작성할 writer를 얻습니다.
w, err := c.Data()
if err != nil {
return err
}
_, err = w.Write(msg)
if err != nil {
return err
}
// writer를 닫아 본문 입력의 끝을 표시합니다
// (SMTP 프로토콜에서 끝은 "\\r\\n.\\r\\n"으로 표시됩니다).
err = w.Close()
if err != nil {
return err
}

// 6. QUIT 명령을 보내 서버와의 세션을 정상적으로 종료합니다.
return c.Quit()
}

// main 은 진입점으로, Test465를 직접 호출하여 전송을 트리거합니다.
// 실제 비즈니스 통합 시에는 전송 매개변수(계정, 비밀번호, 수신자 등)를
// 구성 또는 함수 인자로 분리하고, Test465의 오류에 대해 더 세밀한
// 처리 및 재시도를 수행하는 것이 좋습니다.
func main() {
Test465()
}




도움말 및 지원

문제 해결에 도움이 되었나요?

피드백