mail-autoconfig/internal/app/outlook.go

136 lines
4.3 KiB
Go
Raw Permalink Normal View History

2024-06-04 20:46:09 +00:00
package app
import (
"bytes"
"encoding/xml"
"io"
"log"
"net/http"
"strings"
"text/template"
"github.com/gin-gonic/gin"
)
const outlookTpl = `
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
<Account>
<AccountType>email</AccountType>
<Action>settings</Action>
{{- if .IMAPEnabled }}
<Protocol>
<Type>IMAP</Type>
<Server>{{ .IMAPServer }}</Server>
<Port>{{ .IMAPPort }}</Port>
<DomainRequired>on</DomainRequired>
<SPA>off</SPA>
<SSL>{{ if .IMAPSSL }}on{{ else }}off{{ end }}</SSL>
<AuthRequired>on</AuthRequired>
<LoginName>{{ .Username }}@{{ .Domain }}</LoginName>
</Protocol>
{{- end }}
{{- if .POP3Enabled }}
<Protocol>
<Type>POP3</Type>
<Server>mail.mdfmultimedia.com</Server>
<Port>995</Port>
<DomainRequired>on</DomainRequired>
<SPA>off</SPA>
<SSL>{{ if .POP3SSL }}on{{ else }}off{{ end }}</SSL>
<AuthRequired>on</AuthRequired>
<LoginName>{{ .Username }}@{{ .Domain }}</LoginName>
</Protocol>
{{- end }}
{{- if .SMTPEnabled }}
<Protocol>
<Type>SMTP</Type>
<Server>mail.mdfmultimedia.com</Server>
<Port>465</Port>
<DomainRequired>on</DomainRequired>
<SPA>off</SPA>
<SSL>{{ if .SMTPSSL }}on{{ else }}off{{ end }}</SSL>
<AuthRequired>on</AuthRequired>
<LoginName>{{ .Username }}@{{ .Domain }}</LoginName>
</Protocol>
{{- end }}
</Account>
</Response>
</Autodiscover>
`
var outlookTemplate *template.Template
func RenderOutlook(g *gin.Context) {
var err error
var body []byte
var domain Domain
var ok bool
var b bytes.Buffer
body, err = io.ReadAll(g.Request.Body)
if err != nil {
g.JSON(404, gin.H{"code": "WRONG_BODY", "message": "malformed request"})
return
}
var e struct {
Address string `xml:"Request>EMailAddress"`
}
err = xml.Unmarshal(body, &e)
if err != nil {
g.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"})
return
}
components := strings.Split(e.Address, "@")
username, reqDomain := components[0], components[1]
domain, ok = Domains[reqDomain]
if !ok {
g.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"})
return
}
domain.Username = username
err = outlookTemplate.Execute(&b, domain)
if err != nil {
log.Fatal(err)
}
g.Header("Content-Type", "application/xml; charset=utf-8")
g.String(http.StatusOK, b.String())
}
// curl -X POST -d @req.xml http://127.0.0.1:8888/autodiscover/autodiscover.xml
// curl --basic -X "POST" -u XXX@YYY -v https://autodiscover-s.outlook.com/autodiscover/autodiscover.xml -H "Content-Type: text/xml" -d @a.txt
/*
<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/mobilesync/requestschema/2006">
<Request>
<EMailAddress>testuser@company.tld</EMailAddress>
<AcceptableResponseSchema>
http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006
</AcceptableResponseSchema>
</Request>
</Autodiscover>
$ curl -d @request.xml -u testuser@company.tld -H "Content-Type: text/xml" -v https://autodiscover.company.tld/autodiscover/autodiscover.xml
*/
/*
1 - Lookup di un record A (o CNAME) per contoso.com che punta ad un web server che risponderà con un URL HTTPS https://contoso.com/Autodiscover/Autodiscover.xml.
2 - Lookup di un record A (o CNAME) per autodiscover.contoso.com che punta ad un web server che risponderà con un URL HTTPS https://autodiscover.contoso.com/Autodiscover/Autodiscover.xml
3 - Lookup di un record A (o CNAME) per contoso.com che punta ad un web server che risponderà con URL HTTP http://autodiscover.contoso.com/Autodiscover/Autodiscover.xml (se avete un reverse proxy o direttamente su Exchange, dovrete fare la configurazione necessaria per implementare lhttp to https redirect)
4 - Lookup di un record SRV per autodiscover._tcp.contoso.com (Questo record deve contenere la porta 443 e lhostname, ad esempio mail.contoso.com, permetendo cosi al client di fare una request in https allURL https://mail.contoso.com/Autodiscover/Autodiscover.xml)
*/