Ответ
Да, приходилось. Для работы с IMAP в Go я бы использовал стандартную де-факто библиотеку github.com/emersion/go-imap и ее экосистему.
Процесс работы с почтой обычно состоит из следующих шагов:
- Подключение к серверу: Установка безопасного соединения с IMAP-сервером, обычно через TLS (
client.DialTLS). - Аутентификация: Вход в систему с использованием логина и пароля (
client.Login). - Выбор почтового ящика (Mailbox): Выбор папки для работы, например,
INBOX(client.Select). - Поиск и получение писем (Search & Fetch): Сначала можно найти ID нужных писем (например, все непрочитанные) с помощью
client.Search, а затем запросить их содержимое (client.Fetch). При запросе можно указать, какие части письма нужны:ENVELOPE(метаданные),BODY[](содержимое),UIDи т.д. - Парсинг MIME-содержимого: Тело письма — это сложная структура (MIME). Для его разбора на текст, HTML и вложения понадобится дополнительная библиотека, например,
net/mailиз стандартной библиотеки илиgithub.com/emersion/go-message.
Пример кода (чтение темы последнего письма):
package main
import (
"log"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
)
func main() {
c, err := client.DialTLS("imap.example.com:993", nil)
if err != nil { log.Fatal(err) }
defer c.Logout()
if err := c.Login("user@example.com", "password"); err != nil {
log.Fatal(err)
}
mbox, err := c.Select("INBOX", true) // true - read-only
if err != nil { log.Fatal(err) }
if mbox.Messages == 0 {
log.Fatal("No messages in inbox")
}
// Берем последнее письмо
seqset := new(imap.SeqSet)
seqset.AddNum(mbox.Messages)
// Запрашиваем его конверт (тема, отправитель и т.д.)
messages := make(chan *imap.Message, 1)
go func() {
if err := c.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope}, messages); err != nil {
log.Fatal(err)
}
}()
msg := <-messages
log.Println("Subject:", msg.Envelope.Subject)
}
Дополнительные возможности:
Библиотека также поддерживает продвинутые функции, такие как команда IDLE, которая позволяет получать уведомления о новых письмах в реальном времени без необходимости постоянно опрашивать сервер (polling).
Ответ 18+ 🔞
Да ты посмотри, какой вопрос подкинули! Приходилось ли мне с почтой через IMAP в Go работать? Да я в этой теме, как говно в проруби, плавал, блядь! Тут главное — не накосячить с библиотеками, а то можно такую кашу заварить, что потом полгода распутывать.
Так, слушай сюда, поехали по шагам, как нормальный человек это делает, а не какой-нибудь полупидор с кривыми руками:
- Подключиться к серверу надо. Ты ж не через дырявое ведро воду носишь? Вот и тут —
client.DialTLS, чтобы всё шифрованно было, а то прочитают твою переписку, и волнение ебать накроет. - Залогиниться. Логин-пароль суешь,
client.Loginвызываешь. Если ошибка — значит, или ты мудак, и пароль забыл, или сервер — пидарас шерстяной. - Выбрать папку. Обычно
INBOX, но можно и в «Спам» заглянуть, если охота приключений.client.Select— и ты в деле. - Письма искать и тащить. Сначала
client.Search— говоришь серверу: «Давай, сука, все непрочитанные!» Он тебе IDшники отдаёт. Потомclient.Fetch— и по этим ID выкачиваешь что надо: заголовки (ENVELOPE), тело (BODY[]), а можно и всё сразу, если хочешь овердохуища трафика. - А вот тут самое интересное — разбор письма. Тело-то приходит одно, а внутри — целый ёперный театр! Текст, HTML, картинки, документы — всё вперемешку, в MIME-формате. Чтобы не сойти с ума, бери
github.com/emersion/go-messageи парсь как бог.
Вот тебе кусок кода для затравки, чтобы просто тему последнего письма прочитать. Смотри, не обосрись:
package main
import (
"log"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
)
func main() {
// Подключаемся, блядь
c, err := client.DialTLS("imap.example.com:993", nil)
if err != nil { log.Fatal(err) }
defer c.Logout() // Не забудь выйти, а то сессия повиснет!
// Логинимся
if err := c.Login("user@example.com", "password"); err != nil {
log.Fatal(err) // Если тут ошибка — пиши пропало
}
// Лезем в папку "Входящие"
mbox, err := c.Select("INBOX", true) // true — только читаем, не портим
if err != nil { log.Fatal(err) }
// Если писем нет — грустно, но жить можно
if mbox.Messages == 0 {
log.Fatal("No messages in inbox")
}
// Берём последнее письмо, оно же самое свежее
seqset := new(imap.SeqSet)
seqset.AddNum(mbox.Messages)
// Тащим только конверт (от кого, тема, дата)
messages := make(chan *imap.Message, 1)
go func() {
if err := c.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope}, messages); err != nil {
log.Fatal(err)
}
}()
// Ловим его из канала
msg := <-messages
log.Println("Subject:", msg.Envelope.Subject) // Ну вот и тема, доволен?
}
А если хочешь реальный движняк — там есть команда IDLE. Это когда ты серверу говоришь: «Слушай, пацан, как только что-то новое прилетит — сразу пинай меня, не жди!» И ты висишь в подключении, а тебе стримом приходят уведомления. Красота, а не жизнь! Главное, не проёбывай таймауты.
Короче, библиотека — огонь. Бери, не ошибёшься. Только MIME эти ебушки-воробушки не забудь правильно распарсить, а то так и будешь смотреть на кучу байт и чесать репу.