mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 06:21:11 +00:00 
			
		
		
		
	Backport #21945 Unfortunately the fallback configuration code for [mailer] that were added in #18982 are incorrect. When you read a value from an ini section that key is added. This leads to a failure of the fallback mechanism. Further there is also a spelling mistake in the startTLS configuration. This PR restructures the mailer code to first map the deprecated settings on to the new ones - and then use ini.MapTo to map those on to the struct with additional validation as necessary. Ref #21744 Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
		
					parent
					
						
							
								cddceb9dca
							
						
					
				
			
			
				commit
				
					
						888384a631
					
				
			
		
					 5 changed files with 96 additions and 94 deletions
				
			
		|  | @ -1550,7 +1550,7 @@ ROUTER = console | ||||||
| ;; Prefix displayed before subject in mail | ;; Prefix displayed before subject in mail | ||||||
| ;SUBJECT_PREFIX = | ;SUBJECT_PREFIX = | ||||||
| ;; | ;; | ||||||
| ;; Mail server protocol. One of "smtp", "smtps", "smtp+startls", "smtp+unix", "sendmail", "dummy". | ;; Mail server protocol. One of "smtp", "smtps", "smtp+starttls", "smtp+unix", "sendmail", "dummy". | ||||||
| ;; - sendmail: use the operating system's `sendmail` command instead of SMTP. This is common on Linux systems. | ;; - sendmail: use the operating system's `sendmail` command instead of SMTP. This is common on Linux systems. | ||||||
| ;; - dummy: send email messages to the log as a testing phase. | ;; - dummy: send email messages to the log as a testing phase. | ||||||
| ;; If your provider does not explicitly say which protocol it uses but does provide a port, | ;; If your provider does not explicitly say which protocol it uses but does provide a port, | ||||||
|  |  | ||||||
|  | @ -672,7 +672,7 @@ and | ||||||
| [Gitea 1.17 configuration document](https://github.com/go-gitea/gitea/blob/release/v1.17/docs/content/doc/advanced/config-cheat-sheet.en-us.md) | [Gitea 1.17 configuration document](https://github.com/go-gitea/gitea/blob/release/v1.17/docs/content/doc/advanced/config-cheat-sheet.en-us.md) | ||||||
| 
 | 
 | ||||||
| - `ENABLED`: **false**: Enable to use a mail service. | - `ENABLED`: **false**: Enable to use a mail service. | ||||||
| - `PROTOCOL`: **\<empty\>**: Mail server protocol. One of "smtp", "smtps", "smtp+startls", "smtp+unix", "sendmail", "dummy". _Before 1.18, this was inferred from a combination of `MAILER_TYPE` and `IS_TLS_ENABLED`._ | - `PROTOCOL`: **\<empty\>**: Mail server protocol. One of "smtp", "smtps", "smtp+starttls", "smtp+unix", "sendmail", "dummy". _Before 1.18, this was inferred from a combination of `MAILER_TYPE` and `IS_TLS_ENABLED`._ | ||||||
|   - SMTP family, if your provider does not explicitly say which protocol it uses but does provide a port, you can set SMTP_PORT instead and this will be inferred. |   - SMTP family, if your provider does not explicitly say which protocol it uses but does provide a port, you can set SMTP_PORT instead and this will be inferred. | ||||||
|   - **sendmail** Use the operating system's `sendmail` command instead of SMTP. This is common on Linux systems. |   - **sendmail** Use the operating system's `sendmail` command instead of SMTP. This is common on Linux systems. | ||||||
|   - **dummy** Send email messages to the log as a testing phase. |   - **dummy** Send email messages to the log as a testing phase. | ||||||
|  |  | ||||||
|  | @ -18,32 +18,33 @@ import ( | ||||||
| // Mailer represents mail service. | // Mailer represents mail service. | ||||||
| type Mailer struct { | type Mailer struct { | ||||||
| 	// Mailer | 	// Mailer | ||||||
| 	Name                 string | 	Name                 string `ini:"NAME"` | ||||||
| 	From                 string | 	From                 string `ini:"FROM"` | ||||||
| 	EnvelopeFrom         string | 	EnvelopeFrom         string `ini:"ENVELOPE_FROM"` | ||||||
| 	OverrideEnvelopeFrom bool `ini:"-"` | 	OverrideEnvelopeFrom bool   `ini:"-"` | ||||||
| 	FromName             string | 	FromName             string `ini:"-"` | ||||||
| 	FromEmail            string | 	FromEmail            string `ini:"-"` | ||||||
| 	SendAsPlainText      bool | 	SendAsPlainText      bool   `ini:"SEND_AS_PLAIN_TEXT"` | ||||||
| 	SubjectPrefix        string | 	SubjectPrefix        string `ini:"SUBJECT_PREFIX"` | ||||||
| 
 | 
 | ||||||
| 	// SMTP sender | 	// SMTP sender | ||||||
| 	Protocol             string | 	Protocol             string `ini:"PROTOCOL"` | ||||||
| 	SMTPAddr             string | 	SMTPAddr             string `ini:"SMTP_ADDR"` | ||||||
| 	SMTPPort             string | 	SMTPPort             string `ini:"SMTP_PORT"` | ||||||
| 	User, Passwd         string | 	User                 string `ini:"USER"` | ||||||
| 	EnableHelo           bool | 	Passwd               string `ini:"PASSWD"` | ||||||
| 	HeloHostname         string | 	EnableHelo           bool   `ini:"ENABLE_HELO"` | ||||||
| 	ForceTrustServerCert bool | 	HeloHostname         string `ini:"HELO_HOSTNAME"` | ||||||
| 	UseClientCert        bool | 	ForceTrustServerCert bool   `ini:"FORCE_TRUST_SERVER_CERT"` | ||||||
| 	ClientCertFile       string | 	UseClientCert        bool   `ini:"USE_CLIENT_CERT"` | ||||||
| 	ClientKeyFile        string | 	ClientCertFile       string `ini:"CLIENT_CERT_FILE"` | ||||||
|  | 	ClientKeyFile        string `ini:"CLIENT_KEY_FILE"` | ||||||
| 
 | 
 | ||||||
| 	// Sendmail sender | 	// Sendmail sender | ||||||
| 	SendmailPath        string | 	SendmailPath        string        `ini:"SENDMAIL_PATH"` | ||||||
| 	SendmailArgs        []string | 	SendmailArgs        []string      `ini:"-"` | ||||||
| 	SendmailTimeout     time.Duration | 	SendmailTimeout     time.Duration `ini:"SENDMAIL_TIMEOUT"` | ||||||
| 	SendmailConvertCRLF bool | 	SendmailConvertCRLF bool          `ini:"SENDMAIL_CONVERT_CRLF"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // MailService the global mailer | // MailService the global mailer | ||||||
|  | @ -56,35 +57,12 @@ func newMailService() { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	MailService = &Mailer{ | 	// Handle Deprecations and map on to new configuration | ||||||
| 		Name:            sec.Key("NAME").MustString(AppName), |  | ||||||
| 		SendAsPlainText: sec.Key("SEND_AS_PLAIN_TEXT").MustBool(false), |  | ||||||
| 
 |  | ||||||
| 		Protocol:             sec.Key("PROTOCOL").In("", []string{"smtp", "smtps", "smtp+startls", "smtp+unix", "sendmail", "dummy"}), |  | ||||||
| 		SMTPAddr:             sec.Key("SMTP_ADDR").String(), |  | ||||||
| 		SMTPPort:             sec.Key("SMTP_PORT").String(), |  | ||||||
| 		User:                 sec.Key("USER").String(), |  | ||||||
| 		Passwd:               sec.Key("PASSWD").String(), |  | ||||||
| 		EnableHelo:           sec.Key("ENABLE_HELO").MustBool(true), |  | ||||||
| 		HeloHostname:         sec.Key("HELO_HOSTNAME").String(), |  | ||||||
| 		ForceTrustServerCert: sec.Key("FORCE_TRUST_SERVER_CERT").MustBool(false), |  | ||||||
| 		UseClientCert:        sec.Key("USE_CLIENT_CERT").MustBool(false), |  | ||||||
| 		ClientCertFile:       sec.Key("CLIENT_CERT_FILE").String(), |  | ||||||
| 		ClientKeyFile:        sec.Key("CLIENT_KEY_FILE").String(), |  | ||||||
| 		SubjectPrefix:        sec.Key("SUBJECT_PREFIX").MustString(""), |  | ||||||
| 
 |  | ||||||
| 		SendmailPath:        sec.Key("SENDMAIL_PATH").MustString("sendmail"), |  | ||||||
| 		SendmailTimeout:     sec.Key("SENDMAIL_TIMEOUT").MustDuration(5 * time.Minute), |  | ||||||
| 		SendmailConvertCRLF: sec.Key("SENDMAIL_CONVERT_CRLF").MustBool(true), |  | ||||||
| 	} |  | ||||||
| 	MailService.From = sec.Key("FROM").MustString(MailService.User) |  | ||||||
| 	MailService.EnvelopeFrom = sec.Key("ENVELOPE_FROM").MustString("") |  | ||||||
| 
 |  | ||||||
| 	// FIXME: DEPRECATED to be removed in v1.19.0 | 	// FIXME: DEPRECATED to be removed in v1.19.0 | ||||||
| 	deprecatedSetting("mailer", "MAILER_TYPE", "mailer", "PROTOCOL") | 	deprecatedSetting("mailer", "MAILER_TYPE", "mailer", "PROTOCOL") | ||||||
| 	if sec.HasKey("MAILER_TYPE") && !sec.HasKey("PROTOCOL") { | 	if sec.HasKey("MAILER_TYPE") && !sec.HasKey("PROTOCOL") { | ||||||
| 		if sec.Key("MAILER_TYPE").String() == "sendmail" { | 		if sec.Key("MAILER_TYPE").String() == "sendmail" { | ||||||
| 			MailService.Protocol = "sendmail" | 			sec.Key("PROTOCOL").MustString("sendmail") | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -96,31 +74,91 @@ func newMailService() { | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Fatal("Invalid mailer.HOST (%s): %v", givenHost, err) | 			log.Fatal("Invalid mailer.HOST (%s): %v", givenHost, err) | ||||||
| 		} | 		} | ||||||
| 		MailService.SMTPAddr = addr | 		sec.Key("SMTP_ADDR").MustString(addr) | ||||||
| 		MailService.SMTPPort = port | 		sec.Key("SMTP_PORT").MustString(port) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// FIXME: DEPRECATED to be removed in v1.19.0 | 	// FIXME: DEPRECATED to be removed in v1.19.0 | ||||||
| 	deprecatedSetting("mailer", "IS_TLS_ENABLED", "mailer", "PROTOCOL") | 	deprecatedSetting("mailer", "IS_TLS_ENABLED", "mailer", "PROTOCOL") | ||||||
| 	if sec.HasKey("IS_TLS_ENABLED") && !sec.HasKey("PROTOCOL") { | 	if sec.HasKey("IS_TLS_ENABLED") && !sec.HasKey("PROTOCOL") { | ||||||
| 		if sec.Key("IS_TLS_ENABLED").MustBool() { | 		if sec.Key("IS_TLS_ENABLED").MustBool() { | ||||||
| 			MailService.Protocol = "smtps" | 			sec.Key("PROTOCOL").MustString("smtps") | ||||||
| 		} else { | 		} else { | ||||||
| 			MailService.Protocol = "smtp+startls" | 			sec.Key("PROTOCOL").MustString("smtp+starttls") | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// FIXME: DEPRECATED to be removed in v1.19.0 | ||||||
|  | 	deprecatedSetting("mailer", "DISABLE_HELO", "mailer", "ENABLE_HELO") | ||||||
|  | 	if sec.HasKey("DISABLE_HELO") && !sec.HasKey("ENABLE_HELO") { | ||||||
|  | 		sec.Key("ENABLE_HELO").MustBool(!sec.Key("DISABLE_HELO").MustBool()) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// FIXME: DEPRECATED to be removed in v1.19.0 | ||||||
|  | 	deprecatedSetting("mailer", "SKIP_VERIFY", "mailer", "FORCE_TRUST_SERVER_CERT") | ||||||
|  | 	if sec.HasKey("SKIP_VERIFY") && !sec.HasKey("FORCE_TRUST_SERVER_CERT") { | ||||||
|  | 		sec.Key("FORCE_TRUST_SERVER_CERT").MustBool(sec.Key("SKIP_VERIFY").MustBool()) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// FIXME: DEPRECATED to be removed in v1.19.0 | ||||||
|  | 	deprecatedSetting("mailer", "USE_CERTIFICATE", "mailer", "USE_CLIENT_CERT") | ||||||
|  | 	if sec.HasKey("USE_CERTIFICATE") && !sec.HasKey("USE_CLIENT_CERT") { | ||||||
|  | 		sec.Key("USE_CLIENT_CERT").MustBool(sec.Key("USE_CERTIFICATE").MustBool()) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// FIXME: DEPRECATED to be removed in v1.19.0 | ||||||
|  | 	deprecatedSetting("mailer", "CERT_FILE", "mailer", "CLIENT_CERT_FILE") | ||||||
|  | 	if sec.HasKey("CERT_FILE") && !sec.HasKey("CLIENT_CERT_FILE") { | ||||||
|  | 		sec.Key("CERT_FILE").MustString(sec.Key("CERT_FILE").String()) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// FIXME: DEPRECATED to be removed in v1.19.0 | ||||||
|  | 	deprecatedSetting("mailer", "KEY_FILE", "mailer", "CLIENT_KEY_FILE") | ||||||
|  | 	if sec.HasKey("KEY_FILE") && !sec.HasKey("CLIENT_KEY_FILE") { | ||||||
|  | 		sec.Key("KEY_FILE").MustString(sec.Key("KEY_FILE").String()) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// FIXME: DEPRECATED to be removed in v1.19.0 | ||||||
|  | 	deprecatedSetting("mailer", "ENABLE_HTML_ALTERNATIVE", "mailer", "SEND_AS_PLAIN_TEXT") | ||||||
|  | 	if sec.HasKey("ENABLE_HTML_ALTERNATIVE") && !sec.HasKey("SEND_AS_PLAIN_TEXT") { | ||||||
|  | 		sec.Key("SEND_AS_PLAIN_TEXT").MustBool(!sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(false)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if sec.HasKey("PROTOCOL") && sec.Key("PROTOCOL").String() == "smtp+startls" { | ||||||
|  | 		log.Error("Deprecated fallback `[mailer]` `PROTOCOL = smtp+startls` present. Use `[mailer]` `PROTOCOL = smtp+starttls`` instead. This fallback will be removed in v1.19.0") | ||||||
|  | 		sec.Key("PROTOCOL").SetValue("smtp+starttls") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Set default values & validate | ||||||
|  | 	sec.Key("NAME").MustString(AppName) | ||||||
|  | 	sec.Key("PROTOCOL").In("", []string{"smtp", "smtps", "smtp+starttls", "smtp+unix", "sendmail", "dummy"}) | ||||||
|  | 	sec.Key("ENABLE_HELO").MustBool(true) | ||||||
|  | 	sec.Key("FORCE_TRUST_SERVER_CERT").MustBool(false) | ||||||
|  | 	sec.Key("USE_CLIENT_CERT").MustBool(false) | ||||||
|  | 	sec.Key("SENDMAIL_PATH").MustString("sendmail") | ||||||
|  | 	sec.Key("SENDMAIL_TIMEOUT").MustDuration(5 * time.Minute) | ||||||
|  | 	sec.Key("SENDMAIL_CONVERT_CRLF").MustBool(true) | ||||||
|  | 	sec.Key("FROM").MustString(sec.Key("USER").String()) | ||||||
|  | 
 | ||||||
|  | 	// Now map the values on to the MailService | ||||||
|  | 	MailService = &Mailer{} | ||||||
|  | 	if err := sec.MapTo(MailService); err != nil { | ||||||
|  | 		log.Fatal("Unable to map [mailer] section on to MailService. Error: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Infer SMTPPort if not set | ||||||
| 	if MailService.SMTPPort == "" { | 	if MailService.SMTPPort == "" { | ||||||
| 		switch MailService.Protocol { | 		switch MailService.Protocol { | ||||||
| 		case "smtp": | 		case "smtp": | ||||||
| 			MailService.SMTPPort = "25" | 			MailService.SMTPPort = "25" | ||||||
| 		case "smtps": | 		case "smtps": | ||||||
| 			MailService.SMTPPort = "465" | 			MailService.SMTPPort = "465" | ||||||
| 		case "smtp+startls": | 		case "smtp+starttls": | ||||||
| 			MailService.SMTPPort = "587" | 			MailService.SMTPPort = "587" | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// Infer Protocol | ||||||
| 	if MailService.Protocol == "" { | 	if MailService.Protocol == "" { | ||||||
| 		if strings.ContainsAny(MailService.SMTPAddr, "/\\") { | 		if strings.ContainsAny(MailService.SMTPAddr, "/\\") { | ||||||
| 			MailService.Protocol = "smtp+unix" | 			MailService.Protocol = "smtp+unix" | ||||||
|  | @ -131,7 +169,7 @@ func newMailService() { | ||||||
| 			case "465": | 			case "465": | ||||||
| 				MailService.Protocol = "smtps" | 				MailService.Protocol = "smtps" | ||||||
| 			case "587": | 			case "587": | ||||||
| 				MailService.Protocol = "smtp+startls" | 				MailService.Protocol = "smtp+starttls" | ||||||
| 			default: | 			default: | ||||||
| 				log.Error("unable to infer unspecified mailer.PROTOCOL from mailer.SMTP_PORT = %q, assume using smtps", MailService.SMTPPort) | 				log.Error("unable to infer unspecified mailer.PROTOCOL from mailer.SMTP_PORT = %q, assume using smtps", MailService.SMTPPort) | ||||||
| 				MailService.Protocol = "smtps" | 				MailService.Protocol = "smtps" | ||||||
|  | @ -151,42 +189,6 @@ func newMailService() { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// FIXME: DEPRECATED to be removed in v1.19.0 |  | ||||||
| 	deprecatedSetting("mailer", "DISABLE_HELO", "mailer", "ENABLE_HELO") |  | ||||||
| 	if sec.HasKey("DISABLE_HELO") && !sec.HasKey("ENABLE_HELO") { |  | ||||||
| 		MailService.EnableHelo = !sec.Key("DISABLE_HELO").MustBool() |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// FIXME: DEPRECATED to be removed in v1.19.0 |  | ||||||
| 	deprecatedSetting("mailer", "SKIP_VERIFY", "mailer", "FORCE_TRUST_SERVER_CERT") |  | ||||||
| 	if sec.HasKey("SKIP_VERIFY") && !sec.HasKey("FORCE_TRUST_SERVER_CERT") { |  | ||||||
| 		MailService.ForceTrustServerCert = sec.Key("SKIP_VERIFY").MustBool() |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// FIXME: DEPRECATED to be removed in v1.19.0 |  | ||||||
| 	deprecatedSetting("mailer", "USE_CERTIFICATE", "mailer", "USE_CLIENT_CERT") |  | ||||||
| 	if sec.HasKey("USE_CERTIFICATE") && !sec.HasKey("USE_CLIENT_CERT") { |  | ||||||
| 		MailService.UseClientCert = sec.Key("USE_CLIENT_CERT").MustBool() |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// FIXME: DEPRECATED to be removed in v1.19.0 |  | ||||||
| 	deprecatedSetting("mailer", "CERT_FILE", "mailer", "CLIENT_CERT_FILE") |  | ||||||
| 	if sec.HasKey("CERT_FILE") && !sec.HasKey("CLIENT_CERT_FILE") { |  | ||||||
| 		MailService.ClientCertFile = sec.Key("CERT_FILE").String() |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// FIXME: DEPRECATED to be removed in v1.19.0 |  | ||||||
| 	deprecatedSetting("mailer", "KEY_FILE", "mailer", "CLIENT_KEY_FILE") |  | ||||||
| 	if sec.HasKey("KEY_FILE") && !sec.HasKey("CLIENT_KEY_FILE") { |  | ||||||
| 		MailService.ClientKeyFile = sec.Key("KEY_FILE").String() |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// FIXME: DEPRECATED to be removed in v1.19.0 |  | ||||||
| 	deprecatedSetting("mailer", "ENABLE_HTML_ALTERNATIVE", "mailer", "SEND_AS_PLAIN_TEXT") |  | ||||||
| 	if sec.HasKey("ENABLE_HTML_ALTERNATIVE") && !sec.HasKey("SEND_AS_PLAIN_TEXT") { |  | ||||||
| 		MailService.SendAsPlainText = !sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(false) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if MailService.From != "" { | 	if MailService.From != "" { | ||||||
| 		parsed, err := mail.ParseAddress(MailService.From) | 		parsed, err := mail.ParseAddress(MailService.From) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
|  |  | ||||||
|  | @ -603,7 +603,7 @@ func LoadForTest(extraConfigs ...string) { | ||||||
| 
 | 
 | ||||||
| func deprecatedSetting(oldSection, oldKey, newSection, newKey string) { | func deprecatedSetting(oldSection, oldKey, newSection, newKey string) { | ||||||
| 	if Cfg.Section(oldSection).HasKey(oldKey) { | 	if Cfg.Section(oldSection).HasKey(oldKey) { | ||||||
| 		log.Error("Deprecated fallback `[%s]` `%s` present. Use `[%s]` `%s` instead. This fallback will be removed in v1.18.0", oldSection, oldKey, newSection, newKey) | 		log.Error("Deprecated fallback `[%s]` `%s` present. Use `[%s]` `%s` instead. This fallback will be removed in v1.19.0", oldSection, oldKey, newSection, newKey) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -166,7 +166,7 @@ func (s *smtpSender) Send(from string, to []string, msg io.WriterTo) error { | ||||||
| 	defer conn.Close() | 	defer conn.Close() | ||||||
| 
 | 
 | ||||||
| 	var tlsconfig *tls.Config | 	var tlsconfig *tls.Config | ||||||
| 	if opts.Protocol == "smtps" || opts.Protocol == "smtp+startls" { | 	if opts.Protocol == "smtps" || opts.Protocol == "smtp+starttls" { | ||||||
| 		tlsconfig = &tls.Config{ | 		tlsconfig = &tls.Config{ | ||||||
| 			InsecureSkipVerify: opts.ForceTrustServerCert, | 			InsecureSkipVerify: opts.ForceTrustServerCert, | ||||||
| 			ServerName:         opts.SMTPAddr, | 			ServerName:         opts.SMTPAddr, | ||||||
|  | @ -208,7 +208,7 @@ func (s *smtpSender) Send(from string, to []string, msg io.WriterTo) error { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if opts.Protocol == "smtp+startls" { | 	if opts.Protocol == "smtp+starttls" { | ||||||
| 		hasStartTLS, _ := client.Extension("STARTTLS") | 		hasStartTLS, _ := client.Extension("STARTTLS") | ||||||
| 		if hasStartTLS { | 		if hasStartTLS { | ||||||
| 			if err = client.StartTLS(tlsconfig); err != nil { | 			if err = client.StartTLS(tlsconfig); err != nil { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue