Ok pour la lecture des mails, reste à voir comment les servir via http

This commit is contained in:
Laurent Ulrich
2025-07-29 20:40:01 +02:00
parent 881f09fa20
commit e9676f8136
5 changed files with 265 additions and 55 deletions

View File

@@ -6,6 +6,8 @@ import (
"io"
"log"
"mime"
"strconv"
"strings"
"github.com/emersion/go-imap/v2"
"github.com/emersion/go-imap/v2/imapclient"
@@ -15,12 +17,28 @@ import (
type MailBox struct {
Server string
Port uint16
User string
Password string
SSL string
InBox string
Client *imapclient.Client
}
func (mb *MailBox) Configure(conf *MailBoxConfiguration) error {
mb.Server = conf.Server
port, err := strconv.ParseUint(conf.Port, 10, 16)
if err != nil {
return err
}
mb.Port = uint16(port)
mb.User = conf.User
mb.Password = conf.Password
mb.SSL = conf.SSL
mb.InBox = conf.InBox
return nil
}
func (mb *MailBox) ListMessages() (string, error) {
return "", nil
}
@@ -30,9 +48,19 @@ func (mb *MailBox) Connect() error {
WordDecoder: &mime.WordDecoder{CharsetReader: charset.Reader},
}
var err error
mb.Client, err = imapclient.DialTLS(mb.Server, options)
imapServer := fmt.Sprintf("%s:%d", mb.Server, mb.Port)
switch mb.SSL {
case "SSL/TLS":
mb.Client, err = imapclient.DialTLS(imapServer, options)
case "StartTLS":
mb.Client, err = imapclient.DialStartTLS(imapServer, options)
case "NoTLS":
mb.Client, err = imapclient.DialInsecure(imapServer, options)
default:
return fmt.Errorf("bad tls configuration")
}
if err != nil {
log.Println("Error connnecting to", mb.Server, ":", err)
log.Println("Error connnecting to", imapServer, ":", err)
return err
}
log.Println("Connected")
@@ -41,21 +69,33 @@ func (mb *MailBox) Connect() error {
log.Fatal("failed to login:", err)
}
log.Println("Logged in")
return nil
}
func (mb *MailBox) ListFolders() ([]string, error) {
folders := make([]string, 0)
mailBoxes, err := mb.Client.List("", "%", nil).Collect()
if err != nil {
log.Fatal("Error listing mailboxes", err)
return nil, err
}
for _, mbox := range mailBoxes {
log.Println("mailbox:", mbox.Mailbox)
folders = append(folders, mbox.Mailbox)
}
return folders, nil
}
func (mb *MailBox) GetMessages() ([]BlogEntry, error) {
inbox, err := mb.Client.Select(mb.InBox, nil).Wait()
if err != nil {
log.Fatal("Error selecting mailbox:", mb.InBox, err)
}
log.Println("Inbox has", inbox.NumMessages, "messages")
for i := uint32(0); i <= inbox.NumMessages; i++ {
if inbox.NumMessages <= 0 {
return nil, fmt.Errorf("nomessages")
}
entries := make([]BlogEntry, 0)
for i := uint32(1); i <= inbox.NumMessages; i++ {
var entry BlogEntry
seqSet := imap.SeqSetNum(i)
bodySection := &imap.FetchItemBodySection{}
fetchOptions := &imap.FetchOptions{
@@ -66,44 +106,63 @@ func (mb *MailBox) Connect() error {
if err != nil {
log.Fatal("Error fetching mails:", err)
}
for _, msg := range messages {
log.Println("**************MESSAGE**************")
log.Println("From:", msg.Envelope.From)
log.Println("To:", msg.Envelope.To)
log.Println("Date:", msg.Envelope.Date)
log.Println("Subject:", msg.Envelope.Subject)
entry.Title = strings.Trim(messages[0].Envelope.Subject, "\t ")
if !strings.HasPrefix(strings.ToLower(entry.Title), "blog ") {
continue
}
section := msg.FindBodySection(bodySection)
ioReader := bytes.NewReader(section)
mailReader, err := mail.CreateReader(ioReader)
if err != nil {
log.Fatalf("failed to create mail reader: %v", err)
entry.Id = messages[0].Envelope.MessageID
entry.Title = entry.Title[5:]
entry.Author = messages[0].Envelope.From[0].Name
section := messages[0].FindBodySection(bodySection)
ioReader := bytes.NewReader(section)
mailReader, err := mail.CreateReader(ioReader)
if err != nil {
return nil, err
}
for {
part, err := mailReader.NextPart()
if err == io.EOF {
break
} else if err != nil {
return nil, err
}
for {
part, err := mailReader.NextPart()
if err == io.EOF {
break
} else if err != nil {
log.Fatal("Error reading part", err)
}
log.Println("------------PART-----------")
fmt.Println("Content-Type:", part.Header.Get("Content-Type"))
fmt.Println("Content-Transfer-Encoding:", part.Header.Get("Content-Transfer-Encoding"))
fmt.Println("header:", part.Header)
switch header := part.Header.(type) {
case *mail.AttachmentHeader:
switch part.Header.(type) {
case *mail.AttachmentHeader:
/*
filename, _ := header.Filename()
log.Println("------------FILE-----------")
log.Println("Attachment:", filename)
case *mail.InlineHeader:
log.Println("------------INLINE-----------")
body, _ := io.ReadAll(part.Body)
log.Println(string(body))
*/
case *mail.InlineHeader:
body, _ := io.ReadAll(part.Body)
contentTypeFull := strings.TrimPrefix(
strings.ToLower(part.Header.Get("Content-Type")), "content-type")
mediaType, _, err := mime.ParseMediaType(strings.TrimLeft(contentTypeFull, ": "))
if err != nil {
return nil, err
}
switch mediaType {
case "text/plain":
entry.Text = string(body)
case "text/html":
entry.HTML = string(body)
default:
log.Println("Content-Type:", part.Header.Get("Content-Type"))
}
default:
log.Printf("Unkown part type %+v", part)
}
}
entries = append(entries, entry)
}
return nil
return entries, nil
}
func (mb *MailBox) Close() {