diff --git a/Deploy/harbor.cfg b/Deploy/harbor.cfg index 90dc66540..4928f30cd 100644 --- a/Deploy/harbor.cfg +++ b/Deploy/harbor.cfg @@ -14,6 +14,7 @@ email_server_port = 25 email_username = sample_admin@mydomain.com email_password = abc email_from = admin +email_ssl = false ##The password of Harbor admin, change this before any production use. harbor_admin_password= Harbor12345 diff --git a/Deploy/prepare b/Deploy/prepare index 5571e3c20..60ac3a425 100755 --- a/Deploy/prepare +++ b/Deploy/prepare @@ -29,6 +29,7 @@ email_server_port = rcp.get("configuration", "email_server_port") email_username = rcp.get("configuration", "email_username") email_password = rcp.get("configuration", "email_password") email_from = rcp.get("configuration", "email_from") +email_ssl = rcp.get("configuration", "email_ssl") harbor_admin_password = rcp.get("configuration", "harbor_admin_password") auth_mode = rcp.get("configuration", "auth_mode") ldap_url = rcp.get("configuration", "ldap_url") @@ -85,6 +86,7 @@ render(os.path.join(templates_dir, "ui", "app.conf"), email_user_name=email_username, email_user_password=email_password, email_from=email_from, + email_ssl=email_ssl, ui_url=ui_url) render(os.path.join(templates_dir, "registry", "config.yml"), diff --git a/Deploy/templates/ui/app.conf b/Deploy/templates/ui/app.conf index 63dbd3451..99c60f77b 100644 --- a/Deploy/templates/ui/app.conf +++ b/Deploy/templates/ui/app.conf @@ -14,3 +14,4 @@ port = $email_server_port username = $email_user_name password = $email_user_password from = $email_from +ssl = $email_ssl diff --git a/docs/installation_guide.md b/docs/installation_guide.md index 56d0c5152..f030db422 100644 --- a/docs/installation_guide.md +++ b/docs/installation_guide.md @@ -29,12 +29,13 @@ At minimum, you need to change the **hostname** attribute in **harbor.cfg**. The **hostname**: The hostname for a user to access the user interface and the registry service. It should be the IP address or the fully qualified domain name (FQDN) of your target machine, for example 192.168.1.10 or reg.yourdomain.com . Do NOT use localhost or 127.0.0.1 for the hostname because the registry service needs to be accessed by external clients. **ui_url_protocol**: The protocol for accessing the user interface and the token/notification service, by default it is http. To set up the https protocol, refer to [Configuring Harbor with HTTPS Access](configure_https.md). -**Email settings**: the following 5 attributes are used to send an email to reset a user's password, they are not mandatory unless the password reset function is needed in Harbor. +**Email settings**: the following 6 attributes are used to send an email to reset a user's password, they are not mandatory unless the password reset function is needed in Harbor. By default SSL connection is not enabled, if your smtp server(such as exmail.qq.com) requires SSL connection and doesn't support STARTTLS, then you should enable it by set **email_ssl = true**. * email_server = smtp.mydomain.com * email_server_port = 25 * email_username = sample_admin@mydomain.com * email_password = abc * email_from = admin +* email_ssl = false **harbor_admin_password**: The password for the administrator of Harbor, by default the password is Harbor12345, the user name is admin. **auth_mode**: The authentication mode of Harbor. By default it is *db_auth*, i.e. the credentials are stored in a database. Please set it to *ldap_auth* if you want to verify user's credentials against an LDAP server. diff --git a/utils/mail.go b/utils/mail.go index 8dca9f413..fc2843e2c 100644 --- a/utils/mail.go +++ b/utils/mail.go @@ -17,6 +17,8 @@ package utils import ( "bytes" + "crypto/tls" + "strings" "net/smtp" "text/template" @@ -39,6 +41,7 @@ type MailConfig struct { Port string Username string Password string + TLS bool } var mc MailConfig @@ -58,10 +61,66 @@ func (m Mail) SendMail() error { if err != nil { return err } - return smtp. - SendMail(mc.Host+":"+mc.Port, - smtp.PlainAuth(mc.Identity, mc.Username, mc.Password, mc.Host), - m.From, m.To, mailContent.Bytes()) + content := mailContent.Bytes() + + auth := smtp.PlainAuth(mc.Identity, mc.Username, mc.Password, mc.Host) + if mc.TLS { + err = sendMailWithTLS(m, auth, content) + } else { + err = sendMail(m, auth, content) + } + + return err +} + +func sendMail(m Mail, auth smtp.Auth, content []byte) error { + return smtp.SendMail(mc.Host+":"+mc.Port, auth, m.From, m.To, content) +} + +func sendMailWithTLS(m Mail, auth smtp.Auth, content []byte) error { + conn, err := tls.Dial("tcp", mc.Host+":"+mc.Port, nil) + if err != nil { + return err + } + + client, err := smtp.NewClient(conn, mc.Host) + if err != nil { + return err + } + defer client.Close() + + if ok, _ := client.Extension("AUTH"); ok { + if err = client.Auth(auth); err != nil { + return err + } + } + + if err = client.Mail(m.From); err != nil { + return err + } + + for _, to := range m.To { + if err = client.Rcpt(to); err != nil { + return err + } + } + + w, err := client.Data() + if err != nil { + return err + } + + _, err = w.Write(content) + if err != nil { + return err + } + + err = w.Close() + if err != nil { + return err + } + + return client.Quit() } func loadConfig() { @@ -69,11 +128,17 @@ func loadConfig() { if err != nil { panic(err) } + + var useTLS = false + if config["ssl"] != "" && strings.ToLower(config["ssl"]) == "true" { + useTLS = true + } mc = MailConfig{ Identity: "Mail Config", Host: config["host"], Port: config["port"], Username: config["username"], Password: config["password"], + TLS: useTLS, } }