141 lines
3.5 KiB
Go
141 lines
3.5 KiB
Go
package autoconfig
|
|
|
|
import (
|
|
"context"
|
|
"encoding/xml"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const autoconfigTimeout = 4 * time.Second
|
|
|
|
type mozillaConfig struct {
|
|
XMLName xml.Name `xml:"clientConfig"`
|
|
EmailProvider struct {
|
|
ID string `xml:"id,attr"`
|
|
Domain []string `xml:"domain"`
|
|
DisplayName string `xml:"displayName"`
|
|
IncomingServers []mozillaServer `xml:"incomingServer"`
|
|
OutgoingServers []mozillaServer `xml:"outgoingServer"`
|
|
} `xml:"emailProvider"`
|
|
}
|
|
|
|
type mozillaServer struct {
|
|
Type string `xml:"type,attr"`
|
|
Hostname string `xml:"hostname"`
|
|
Port int `xml:"port"`
|
|
SocketType string `xml:"socketType"`
|
|
Username string `xml:"username"`
|
|
}
|
|
|
|
func fetchMozillaAutoconfig(ctx context.Context, domain string) (Result, bool) {
|
|
urls := []string{
|
|
fmt.Sprintf("https://autoconfig.%s/mail/config-v1.1.xml", domain),
|
|
fmt.Sprintf("https://%s/.well-known/autoconfig/mail/config-v1.1.xml", domain),
|
|
fmt.Sprintf("https://autoconfig.thunderbird.net/v1.1/%s", domain),
|
|
}
|
|
client := &http.Client{Timeout: autoconfigTimeout}
|
|
for _, u := range urls {
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
req.Header.Set("User-Agent", "Ultimail-Autoconfig/1.0")
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
body, readErr := io.ReadAll(io.LimitReader(resp.Body, 256<<10))
|
|
_ = resp.Body.Close()
|
|
if readErr != nil || resp.StatusCode != http.StatusOK {
|
|
continue
|
|
}
|
|
if r, ok := parseMozillaConfig(body, domain); ok {
|
|
return r, true
|
|
}
|
|
}
|
|
return Result{}, false
|
|
}
|
|
|
|
func parseMozillaConfig(data []byte, domain string) (Result, bool) {
|
|
var cfg mozillaConfig
|
|
if err := xml.Unmarshal(data, &cfg); err != nil {
|
|
return Result{}, false
|
|
}
|
|
var imapHost string
|
|
var imapPort int
|
|
var imapTLS bool
|
|
var smtpHost string
|
|
var smtpPort int
|
|
var smtpTLS bool
|
|
|
|
for _, s := range cfg.EmailProvider.IncomingServers {
|
|
if strings.EqualFold(s.Type, "imap") && imapHost == "" {
|
|
imapHost = strings.TrimSpace(s.Hostname)
|
|
imapPort = s.Port
|
|
imapTLS = socketUsesTLS(s.SocketType)
|
|
if imapPort == 0 {
|
|
imapPort = 993
|
|
}
|
|
}
|
|
}
|
|
for _, s := range cfg.EmailProvider.OutgoingServers {
|
|
if strings.EqualFold(s.Type, "smtp") && smtpHost == "" {
|
|
smtpHost = strings.TrimSpace(s.Hostname)
|
|
smtpPort = s.Port
|
|
smtpTLS = socketUsesTLS(s.SocketType)
|
|
if smtpPort == 0 {
|
|
smtpPort = 587
|
|
}
|
|
}
|
|
}
|
|
if imapHost == "" && smtpHost == "" {
|
|
return Result{}, false
|
|
}
|
|
name := strings.TrimSpace(cfg.EmailProvider.DisplayName)
|
|
if name == "" {
|
|
name = cfg.EmailProvider.ID
|
|
}
|
|
if name == "" {
|
|
name = domain
|
|
}
|
|
return Result{
|
|
Domain: domain,
|
|
ProviderID: "autoconfig",
|
|
ProviderName: name,
|
|
Source: "autoconfig",
|
|
Confidence: "medium",
|
|
IMAPHost: imapHost,
|
|
IMAPPort: imapPort,
|
|
IMAPTLS: imapTLS,
|
|
SMTPHost: smtpHost,
|
|
SMTPPort: smtpPort,
|
|
SMTPTLS: smtpTLS,
|
|
UsernameHint: mozillaUsernameHint(cfg.EmailProvider.IncomingServers),
|
|
AuthMethods: []string{"password"},
|
|
Notes: []string{"Configuration issue de l'autoconfiguration Mozilla/Thunderbird."},
|
|
}, true
|
|
}
|
|
|
|
func socketUsesTLS(socketType string) bool {
|
|
switch strings.ToUpper(strings.TrimSpace(socketType)) {
|
|
case "SSL", "TLS", "STARTTLS":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func mozillaUsernameHint(servers []mozillaServer) string {
|
|
for _, s := range servers {
|
|
u := strings.ToLower(strings.TrimSpace(s.Username))
|
|
if strings.Contains(u, "%emailaddress%") {
|
|
return "email"
|
|
}
|
|
}
|
|
return "email"
|
|
}
|