Detailed changes
@@ -27,6 +27,7 @@ type Account struct {
IMAPPort int `json:"imap_port,omitempty"`
SMTPServer string `json:"smtp_server,omitempty"`
SMTPPort int `json:"smtp_port,omitempty"`
+ Insecure bool `json:"insecure,omitempty"`
}
// MailingList represents a named group of email addresses.
@@ -170,6 +171,7 @@ func LoadConfig() (*Config, error) {
IMAPPort int `json:"imap_port,omitempty"`
SMTPServer string `json:"smtp_server,omitempty"`
SMTPPort int `json:"smtp_port,omitempty"`
+ Insecure bool `json:"insecure,omitempty"`
}
type diskConfig struct {
Accounts []rawAccount `json:"accounts"`
@@ -215,6 +217,7 @@ func LoadConfig() (*Config, error) {
IMAPPort: rawAcc.IMAPPort,
SMTPServer: rawAcc.SMTPServer,
SMTPPort: rawAcc.SMTPPort,
+ Insecure: rawAcc.Insecure,
}
if rawAcc.Password != "" {
@@ -2,6 +2,7 @@ package fetcher
import (
"bytes"
+ "crypto/tls"
"encoding/base64"
"fmt"
"io"
@@ -111,9 +112,30 @@ func connect(account *config.Account) (*client.Client, error) {
}
addr := fmt.Sprintf("%s:%d", imapServer, imapPort)
- c, err := client.DialTLS(addr, nil)
- if err != nil {
- return nil, err
+
+ tlsConfig := &tls.Config{
+ ServerName: imapServer,
+ InsecureSkipVerify: account.Insecure,
+ }
+
+ var c *client.Client
+ var err error
+
+ // If using standard non-implicit ports (1143 or 143), use Dial + STARTTLS
+ if imapPort == 1143 || imapPort == 143 {
+ c, err = client.Dial(addr)
+ if err != nil {
+ return nil, err
+ }
+ if err := c.StartTLS(tlsConfig); err != nil {
+ return nil, err
+ }
+ } else {
+ // Otherwise default to implicit TLS (port 993)
+ c, err = client.DialTLS(addr, tlsConfig)
+ if err != nil {
+ return nil, err
+ }
}
if err := c.Login(account.Email, account.Password); err != nil {
@@ -3,6 +3,7 @@ package sender
import (
"bytes"
"crypto/rand"
+ "crypto/tls"
"encoding/base64"
"fmt"
"mime"
@@ -166,7 +167,63 @@ func SendEmail(account *config.Account, to, cc, bcc []string, subject, plainBody
allRecipients = append(allRecipients, bcc...)
addr := fmt.Sprintf("%s:%d", smtpServer, smtpPort)
- return smtp.SendMail(addr, auth, account.Email, allRecipients, msg.Bytes())
+
+ // Custom SMTP dialer to support skipping TLS verification for Proton Bridge
+ c, err := smtp.Dial(addr)
+ if err != nil {
+ return err
+ }
+ defer c.Close()
+
+ if err = c.Hello("localhost"); err != nil {
+ return err
+ }
+
+ // Trigger STARTTLS if supported
+ if ok, _ := c.Extension("STARTTLS"); ok {
+ tlsConfig := &tls.Config{
+ ServerName: smtpServer,
+ InsecureSkipVerify: account.Insecure,
+ }
+ if err = c.StartTLS(tlsConfig); err != nil {
+ return err
+ }
+ }
+
+ // Authenticate
+ if auth != nil {
+ if ok, _ := c.Extension("AUTH"); ok {
+ if err = c.Auth(auth); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Send Envelope
+ if err = c.Mail(account.Email); err != nil {
+ return err
+ }
+ for _, r := range allRecipients {
+ if err = c.Rcpt(r); err != nil {
+ return err
+ }
+ }
+
+ // Write Data
+ w, err := c.Data()
+ if err != nil {
+ return err
+ }
+ _, err = w.Write(msg.Bytes())
+ if err != nil {
+ return err
+ }
+ err = w.Close()
+ if err != nil {
+ return err
+ }
+
+ return c.Quit()
}
// wrapBase64 wraps base64-encoded data at 76 characters per line as required by MIME.