Example #1
1
func getThreads(c *imap.Client) ([]Thread, error) {
	set, err := imap.NewSeqSet("1:*")
	cmd, err := imap.Wait(c.Fetch(set, "X-GM-THRID", "UID"))
	if err != nil {
		fmt.Println(err)
		return nil, ErrBadConnection
	}
	var result []Thread
	seen := make(map[string]int)
	for _, rsp := range cmd.Data {
		thrid := imap.AsString(rsp.MessageInfo().Attrs["X-GM-THRID"])
		uid := imap.AsNumber(rsp.MessageInfo().Attrs["UID"])
		if i, ok := seen[thrid]; ok {
			result[i] = append(result[i], uid)
		} else {
			result = append(result, Thread{uid})
			seen[thrid] = len(result) - 1
		}
	}
	return result, nil
}
Example #2
0
// Iterate loops through the given mailbox, filters the results by the currently
// static search filter and invokes the callback for each message.
func (w *IMAPSource) Iterate(mailbox string, callbackFunc IMAPSourceCallback) error {
	w.callbackFunc = callbackFunc
	logger.Debugf("selecting mailbox '%s'", mailbox)
	_, err := w.conn.Select(mailbox, false /* read-write */)
	if err != nil {
		logger.Errorf("failed to select mailbox: %s", err)
		return err
	}
	date := time.Now().Add(-w.minAge)
	dateStr := date.Format(IMAPDateFormat)
	searchFilter := ("UNDELETED SEEN UNFLAGGED (NOT HEADER X-Lemoncrypt \"\") " +
		"(OR SENTBEFORE " + dateStr + " BEFORE " + dateStr + ")")
	logger.Debugf("searching for: %s", searchFilter)
	cmd, err := imap.Wait(w.conn.Search(searchFilter))
	if err != nil {
		logger.Errorf("search failed: %s", err)
		return err
	}
	logger.Debugf("found %d result sets", len(cmd.Data))
	for idx, rsp := range cmd.Data {
		results := rsp.SearchResults()
		logger.Debugf("result set #%d contains %d results", idx, len(results))
		if len(results) == 0 {
			continue
		}
		_ = w.fetchIDs(results)
	}
	logger.Debugf("finally removing mail marked for deletion")
	_, err = imap.Wait(w.conn.Expunge(nil))
	if err != nil {
		logger.Errorf("failed to remove mail marked for deletion: %s", err)
	}
	return err
}
Example #3
0
// getEmails will fetch the full bodies of all emails listed in the given command.
func getEmails(client *imap.Client, cmd *imap.Command) ([]map[string]interface{}, error) {
	var emails []map[string]interface{}
	seq := new(imap.SeqSet)
	for _, rsp := range cmd.Data {
		for _, uid := range rsp.SearchResults() {
			seq.AddNum(uid)
		}
	}
	if seq.Empty() {
		return emails, nil
	}
	fCmd, err := imap.Wait(client.UIDFetch(seq, "INTERNALDATE", "BODY[]", "UID", "RFC822.HEADER"))
	if err != nil {
		return emails, err
	}

	var email map[string]interface{}
	for _, msgData := range fCmd.Data {
		msgFields := msgData.MessageInfo().Attrs
		email, err = newEmailMessage(msgFields)
		if err != nil {
			return emails, err
		}
		emails = append(emails, email)

		// mark message as read
		fSeq := new(imap.SeqSet)
		fSeq.AddNum(imap.AsNumber(msgFields["UID"]))
		_, err = imap.Wait(client.UIDStore(fSeq, "+FLAGS", "\\SEEN"))
		if err != nil {
			return emails, err
		}
	}
	return emails, nil
}
Example #4
0
// SelectMailbox sets up the IMAP connection to use the given mailbox name.
func (w *IMAPTarget) SelectMailbox(mailbox string) error {
	w.curMailbox = mailbox
	logger.Debugf("blindly creating mailbox '%s'", mailbox)
	_, err := imap.Wait(w.conn.Create(mailbox))
	logger.Debugf("mailbox creation ended with err=%s", err)
	logger.Debugf("selecting mailbox '%s'", mailbox)
	_, err = imap.Wait(w.conn.Select(mailbox, false /* readonly=false */))
	if err != nil {
		logger.Errorf("unable to select mailbox '%s': %s", mailbox, err)
	}
	return err
}
Example #5
0
func archive(c *imap.Client, thrid string) error {
	cmd, err := imap.Wait(c.UIDSearch("X-GM-THRID", thrid))
	if err != nil {
		log.Println(err)
		return ErrBadConnection
	}
	if len(cmd.Data) == 0 {
		return nil
	}
	var set imap.SeqSet
	set.AddNum(cmd.Data[0].SearchResults()...)
	_, err = imap.Wait(c.UIDStore(&set, "+FLAGS.SILENT", `(\Deleted)`))
	return err
}
Example #6
0
func fetch(c *imap.Client, user string, thread Thread) ([]*ParsedMail, error) {
	var set imap.SeqSet
	for _, uid := range thread {
		set.AddNum(uid)
	}
	cmd, err := imap.Wait(c.UIDFetch(&set, "BODY[]", "X-GM-MSGID", "X-GM-THRID"))
	if err != nil {
		return nil, ErrBadConnection
	}
	parsed := make([]*ParsedMail, len(cmd.Data))
	for i, rsp := range cmd.Data {
		p, err := parseMail(imap.AsBytes(rsp.MessageInfo().Attrs["BODY[]"]), user)
		if err != nil {
			return nil, err
		}
		link, err := gmailLink(imap.AsString(rsp.MessageInfo().Attrs["X-GM-MSGID"]))
		if err != nil {
			return nil, err
		}
		p.GmailLink = link
		p.Thrid = imap.AsString(rsp.MessageInfo().Attrs["X-GM-THRID"])
		parsed[i] = p
	}
	return parsed, nil
}
Example #7
0
func getEmails(client *imap.Client, cmd *imap.Command, markAsRead, delete bool, responses chan Response) {
	seq := &imap.SeqSet{}
	msgCount := 0
	for _, rsp := range cmd.Data {
		for _, uid := range rsp.SearchResults() {
			msgCount++
			seq.AddNum(uid)
		}
	}

	// nothing to request?! why you even callin me, foolio?
	if seq.Empty() {
		return
	}

	fCmd, err := imap.Wait(client.UIDFetch(seq, "INTERNALDATE", "BODY[]", "UID", "RFC822.HEADER"))
	if err != nil {
		responses <- Response{Err: fmt.Errorf("unable to perform uid fetch: %s", err)}
		return
	}

	var email Email
	for _, msgData := range fCmd.Data {
		msgFields := msgData.MessageInfo().Attrs

		// make sure is a legit response before we attempt to parse it
		// deal with unsolicited FETCH responses containing only flags
		// I'm lookin' at YOU, Gmail!
		// http://mailman13.u.washington.edu/pipermail/imap-protocol/2014-October/002355.html
		// http://stackoverflow.com/questions/26262472/gmail-imap-is-sometimes-returning-bad-results-for-fetch
		if _, ok := msgFields["RFC822.HEADER"]; !ok {
			continue
		}

		email, err = newEmail(msgFields)
		if err != nil {
			responses <- Response{Err: fmt.Errorf("unable to parse email: %s", err)}
			return
		}

		responses <- Response{Email: email}

		if !markAsRead {
			err = removeSeen(client, imap.AsNumber(msgFields["UID"]))
			if err != nil {
				responses <- Response{Err: fmt.Errorf("unable to remove seen flag: %s", err)}
				return
			}
		}

		if delete {
			err = deleteEmail(client, imap.AsNumber(msgFields["UID"]))
			if err != nil {
				responses <- Response{Err: fmt.Errorf("unable to delete email: %s", err)}
				return
			}
		}
	}
	return
}
Example #8
0
// newIMAPClient will initiate a new IMAP connection with the given creds.
func newIMAPClient(info MailboxInfo) (*imap.Client, error) {
	var client *imap.Client
	var err error
	if info.TLS {
		client, err = imap.DialTLS(info.Host, new(tls.Config))
		if err != nil {
			return client, err
		}
	} else {
		client, err = imap.Dial(info.Host)
		if err != nil {
			return client, err
		}
	}

	_, err = client.Login(info.User, info.Pwd)
	if err != nil {
		return client, err
	}

	_, err = imap.Wait(client.Select(info.Folder, info.ReadOnly))
	if err != nil {
		return client, err
	}

	return client, nil
}
Example #9
0
// loadMessages will search and fetch message body
func loadMessages(client *imap.Client, config *Config) error {
	cmd, err := imap.Wait(client.UIDSearch("FROM", client.Quote(config.From), "UNSEEN"))
	if err != nil {
		return err
	}

	seq := new(imap.SeqSet)

	if len(cmd.Data) > 0 {
		seq.AddNum(cmd.Data[0].SearchResults()...)
	}

	if seq.Empty() {
		return nil
	}

	logger.Infof("Fetched UIDs %v", seq)

	cmd, err = imap.Wait(client.UIDFetch(seq, "FLAGS", "INTERNALDATE", "RFC822.SIZE", "BODY[]"))
	if err != nil {
		return err
	}

	for _, rsp := range cmd.Data {
		body, err := fetchMessage(client, rsp.MessageInfo().UID)

		if err != nil {
			logger.Fatal(err)
			return err
		}

		err = writeFileFromBody(bytes.NewReader(body), config)

		if err != nil {
			logger.Fatal(err)
			return err
		}
	}

	if !seq.Empty() {
		_, err = imap.Wait(client.UIDStore(seq, "+FLAGS.SILENT", imap.NewFlagSet(`\Seen`)))
	}

	cmd.Data = nil

	return err
}
Example #10
0
// findUnreadEmails will run a find the UIDs of any unread emails in the
// mailbox.
func findUnreadEmails(conn *imap.Client) (*imap.Command, error) {
	// get headers and UID for UnSeen message in src inbox...
	cmd, err := imap.Wait(conn.UIDSearch("UNSEEN"))
	if err != nil {
		return &imap.Command{}, err
	}
	return cmd, nil
}
Example #11
0
// Append adds the given message to the given mailbox with the given flags and internal
// date.
func (w *IMAPTarget) Append(flags imap.FlagSet, idate *time.Time, msg imap.Literal) error {
	logger.Debugf("appending mail to mailbox '%s'", w.curMailbox)
	delete(flags, "\\Recent")
	_, err := imap.Wait(w.conn.Append(w.curMailbox, flags, idate, msg))
	if err != nil {
		logger.Errorf("failed to store message: %s", err)
	}
	return err
}
Example #12
0
// Login authenticates with the server using the provided credentials.
func (c *IMAPConnection) Login(username, password string) error {
	logger.Debugf("attempting to login as %s", username)
	_, err := imap.Wait(c.conn.Login(username, password))
	if err != nil {
		logger.Errorf("login failed: %s", err)
		return err
	}
	logger.Debugf("logged in")
	return nil
}
Example #13
0
func alterEmail(client *imap.Client, UID uint32, flag string, plus bool) error {
	flg := "-FLAGS"
	if plus {
		flg = "+FLAGS"
	}
	fSeq := &imap.SeqSet{}
	fSeq.AddNum(UID)
	_, err := imap.Wait(client.UIDStore(fSeq, flg, flag))
	if err != nil {
		return err
	}

	return nil
}
Example #14
0
func listCommand(c *cli.Context) {
	var server string
	if c.Args().First() == "" || c.Args().First() == "notes" {
		server = notes
	} else {
		server = exchange
	}
	client := imapConnect(server)
	defer client.Logout(30 * time.Second)
	cmd, _ := imap.Wait(client.List("", "%"))
	fmt.Printf("Ordner auf %s:\n", server)
	for _, r := range cmd.Data {
		fmt.Printf("- %s\n", r.MailboxInfo().Name)
	}
}
Example #15
0
// fetchIDs downloads the messages with the given IDs and invokes the callback for
// each message.
func (w *IMAPSource) fetchIDs(ids []uint32) error {
	set, _ := imap.NewSeqSet("")
	set.AddNum(ids...)
	w.deletionSet, _ = imap.NewSeqSet("")
	cmd, err := w.conn.Fetch(set, "RFC822", "UID", "FLAGS", "INTERNALDATE")
	if err != nil {
		logger.Errorf("FETCH failed: %s", err)
		return err
	}
	for cmd.InProgress() {
		w.conn.Recv(-1)
		for _, rsp := range cmd.Data {
			_ = w.handleMessage(rsp)
		}
		cmd.Data = nil

		// Consume other server data
		for _ = range w.conn.Data {
		}
		w.conn.Data = nil
	}

	if rsp, err := cmd.Result(imap.OK); err != nil {
		if err == imap.ErrAborted {
			logger.Errorf("FETCH command aborted")
		} else {
			logger.Errorf("FETCH error: %s", rsp.Info)
		}
	} else {
		logger.Debugf("FETCH completed without errors")
	}

	if !w.deletePlainCopies {
		return nil
	}

	if w.deletionSet.Empty() {
		return nil
	}

	logger.Debugf("marking mails as deleted")
	_, err = imap.Wait(w.conn.UIDStore(w.deletionSet, "+FLAGS", "(\\Deleted)"))
	if err != nil {
		logger.Errorf("failed to mark set=%v for deletion: %s", w.deletionSet.String(), err)
	}
	return err
}
Example #16
0
// findEmails will run a find the UIDs of any emails that match the search.:
func findEmails(client *imap.Client, search string, since *time.Time) (*imap.Command, error) {
	var specs []imap.Field
	if len(search) > 0 {
		specs = append(specs, search)
	}

	if since != nil {
		sinceStr := since.Format(dateFormat)
		specs = append(specs, "SINCE", sinceStr)
	}

	// get headers and UID for UnSeen message in src inbox...
	cmd, err := imap.Wait(client.UIDSearch(specs...))
	if err != nil {
		return &imap.Command{}, fmt.Errorf("uid search failed: %s", err)
	}
	return cmd, nil
}
Example #17
0
// newIMAPClient will initiate a new IMAP connection with the given creds.
func newIMAPClient(host, username, password, mailbox string) (*imap.Client, error) {
	client, err := imap.DialTLS(host, new(tls.Config))
	if err != nil {
		return client, err
	}

	_, err = client.Login(username, password)
	if err != nil {
		return client, err
	}

	_, err = imap.Wait(client.Select(mailbox, false))
	if err != nil {
		return client, err
	}

	return client, nil
}
Example #18
0
// fetchMessage send UID FETCH command to retrieve message body
func fetchMessage(client *imap.Client, messageUID uint32) ([]byte, error) {
	seq := new(imap.SeqSet)

	seq.AddNum(messageUID)
	cmd, err := imap.Wait(client.UIDFetch(seq, "INTERNALDATE", "BODY[]", "UID", "RFC822.HEADER"))

	if err != nil {
		logger.Errorf("Unable to fetch message (%d): %s", messageUID, err.Error())
		return nil, nil
	}

	if len(cmd.Data) == 0 {
		logger.WithField("uid", messageUID).Info("Unable to fetch message from src: NO DATA")
		return nil, errors.New("message not found")
	}

	msgFields := cmd.Data[0].MessageInfo().Attrs
	body := imap.AsBytes(msgFields["BODY[]"])

	cmd.Data = nil

	return body, nil
}
Example #19
0
func main() {
	token := flag.String("token", "", "The Telegram bot token")
	to := flag.String("to", "", "The mail recipient")
	from := flag.String("from", "", "The mail sender")
	server := flag.String("server", "", "The mail server")
	port := flag.Int("port", 587, "The mail server port")
	user := flag.String("user", "", "")
	pass := flag.String("pass", "", "")
	subject := flag.String("subject", "", "")

	flag.Parse()

	bot, err := telebot.NewBot(*token)
	if err != nil {
		return
	}

	// Fetching Mails and send as Telegram messages

	var (
		c   *imap.Client
		cmd *imap.Command
		rsp *imap.Response
	)

	c, _ = imap.Dial(*server)

	defer c.Logout(30 * time.Second)

	c.Data = nil

	if c.Caps["STARTTLS"] {
		c.StartTLS(nil)
	}

	if c.State() == imap.Login {
		c.Login(*user, *pass)
	}

	cmd, _ = imap.Wait(c.List("", "%"))

	c.Data = nil

	c.Select("INBOX", true)

	set, _ := imap.NewSeqSet("")
	set.Add("1:*")
	cmd, _ = c.Fetch(set, "RFC822.HEADER")

	for cmd.InProgress() {
		c.Recv(-1)

		for _, rsp = range cmd.Data {
			header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"])
			if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
				fmt.Println("|--", msg.Header.Get("FROM"))
			}
		}
		cmd.Data = nil
		c.Data = nil
	}

	if rsp, err := cmd.Result(imap.OK); err != nil {
		if err == imap.ErrAborted {
			fmt.Println("Fetch command aborted")
		} else {
			fmt.Println("Fetch error:", rsp.Info)
		}
	}

	/*
	 * Listen to Telegram messages and send as mail
	 */

	messages := make(chan telebot.Message)
	bot.Listen(messages, 1*time.Second)

	for message := range messages {

		m := gomail.NewMessage()
		m.SetHeader("From", *from)
		m.SetHeader("To", *to)
		m.SetHeader("Subject", *subject)
		m.SetBody("text/html", message.Text)

		d := gomail.NewPlainDialer(*server, *port, *user, *pass)
		d.TLSConfig = &tls.Config{InsecureSkipVerify: true}

		if err := d.DialAndSend(m); err != nil {
			panic(err)
		}
	}
}
Example #20
0
func transferMbox(c *cli.Context) {
	source := c.Args().Get(0)
	target := c.Args().Get(1)
	if source == "" || target == "" {
		log.Fatal("Bitte Quell- und Zielordner angeben, z.B.: mailporter transfer INBOX INBOX")
	}
	n := imapConnect(notes)
	defer n.Logout(30 * time.Second)
	_, err := n.Select(source, true)
	if err != nil {
		log.Fatal("Kein Zugriff auf %s/%s. Fehler: %s", notes, source, err.Error())
	}
	e := imapConnect(exchange)
	defer e.Logout(30 * time.Second)

	fmt.Println("Ermittle zu übertragende Mails...")
	criteria := []string{"ALL"}
	if c.String("before") != "" {
		criteria = append(criteria, "BEFORE "+c.String("before"))
	}
	nc, err := imap.Wait(n.UIDSearch(strings.Join(criteria, " ")))
	var mails []uint32
	for _, r := range nc.Data {
		mails = r.SearchResults()
	}
	reader := bufio.NewReader(os.Stdin)
	fmt.Printf("%d Mails sind zu übertragen. Fortfahren (j oder n)? ", len(mails))
	cont, _ := reader.ReadString('\n')
	if strings.TrimSpace(cont) != "j" {
		return
	}
	fmt.Printf("Übertrage Mails.\n")
	bar := pb.StartNew(len(mails))
	set, _ := imap.NewSeqSet("")
	for _, mid := range mails {
		set.AddNum(mid)
	}
	fetch, err := n.UIDFetch(set, "BODY.PEEK[]")
	if err != nil {
		log.Fatalf("Konnte Mails nicht laden: ", err)
	}
	flags := map[string]bool{
		"\\Seen": true,
	}
	for fetch.InProgress() {
		n.Recv(-1)
		for _, r := range fetch.Data {
			i := r.MessageInfo()
			if i.Size >= maxSize {
				m, err := mail.ReadMessage(bytes.NewReader(imap.AsBytes(i.Attrs["BODY[]"])))
				if err != nil {
					log.Fatal(err)
				}
				date, _ := m.Header.Date()
				datestring := date.Format(time.RFC822)
				fmt.Printf("WARNUNG: Mail '%s' (%s, von %s) ist zu groß für Exchange. Überspringe.\n",
					m.Header.Get("Subject"), datestring, m.Header.Get("From"))
				fetch.Data = nil
				n.Data = nil
				continue
			}
			_, err := imap.Wait(e.Append(target, flags, nil,
				imap.NewLiteral(imap.AsBytes(i.Attrs["BODY[]"]))))
			if err != nil {
				fmt.Printf("WARNUNG: Konnte Mail nicht auf Exchange speichern.\nFehler: %s\n", err.Error())
				m, err := mail.ReadMessage(bytes.NewReader(imap.AsBytes(i.Attrs["BODY[]"])))
				if err != nil {
					log.Fatal(err)
				}
				date, _ := m.Header.Date()
				datestring := date.Format(time.RFC822)
				fmt.Println("Von: ", m.Header.Get("From"))
				fmt.Println("Betreff: ", m.Header.Get("Subject"))
				fmt.Println("Datum: ", datestring)
				e.Logout(0)
				e = imapConnect(exchange)
				defer e.Logout(30 * time.Second)
				fetch.Data = nil
				n.Data = nil
				continue
			}
			bar.Increment()
		}
		fetch.Data = nil
		n.Data = nil
	}
}
Example #21
0
// Fetch email for the specified user and host.
func Fetch(host, user, pass string) {
	c, err := imap.Dial(host)
	if err != nil {
		log.Print(err)
		return
	}
	defer c.Logout(30 * time.Second)

	log.Println("Server says hello:", c.Data[0].Info)
	c.Data = nil

	if c.Caps["STARTTLS"] {
		c.StartTLS(nil)
	}

	if c.State() == imap.Login {
		c.Login(user, pass)
	}

	cmd, err := imap.Wait(c.List("", "%"))
	if err != nil {
		log.Print(err)
		return
	}

	log.Println("\nTop-level mailboxes:")
	for _, rsp := range cmd.Data {
		log.Println("|--", rsp.MailboxInfo())
	}

	for _, rsp := range c.Data {
		log.Println("Server data:", rsp)
	}
	c.Data = nil

	c.Select("INBOX", true)
	log.Print("\nMailbox status:\n", c.Mailbox)

	set, _ := imap.NewSeqSet("")
	if c.Mailbox.Messages >= 10 {
		set.AddRange(c.Mailbox.Messages-9, c.Mailbox.Messages)
	} else {
		set.Add("1:*")
	}
	cmd, _ = c.Fetch(set, "RFC822.HEADER")

	log.Println("\nMost recent messages:")
	for cmd.InProgress() {
		// Wait for the next response (no timeout)
		c.Recv(-1)

		// Process command data
		for _, rsp := range cmd.Data {
			header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"])
			if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
				log.Println("|--", msg.Header.Get("Subject"))
			}
		}
		cmd.Data = nil

		// Process unilateral server data
		for _, rsp := range c.Data {
			log.Println("Server data:", rsp)
		}
		c.Data = nil
	}

	if rsp, err := cmd.Result(imap.OK); err != nil {
		if err == imap.ErrAborted {
			log.Println("Fetch command aborted")
		} else {
			log.Println("Fetch error:", rsp.Info)
		}
	}
}
Example #22
0
// CheckNewMails Check if exist a new mail and post it
func (m *MatterMail) CheckNewMails() error {
	m.debg.Println("CheckNewMails")

	if err := m.CheckImapConnection(); err != nil {
		return err
	}

	var (
		cmd *imap.Command
		rsp *imap.Response
	)

	// Open a mailbox (synchronous command - no need for imap.Wait)
	m.imapClient.Select("INBOX", false)

	var specs []imap.Field
	specs = append(specs, "UNSEEN")
	seq := &imap.SeqSet{}

	// get headers and UID for UnSeen message in src inbox...
	cmd, err := imap.Wait(m.imapClient.UIDSearch(specs...))
	if err != nil {
		m.debg.Println("Error UIDSearch UTF-8:")
		m.debg.Println(err)
		m.debg.Println("Try with US-ASCII")

		// try again with US-ASCII
		cmd, err = imap.Wait(m.imapClient.Send("UID SEARCH", append([]imap.Field{"CHARSET", "US-ASCII"}, specs...)...))
		if err != nil {
			m.eror.Println("UID SEARCH US-ASCII")
			return err
		}
	}

	for _, rsp := range cmd.Data {
		for _, uid := range rsp.SearchResults() {
			m.debg.Println("CheckNewMails:AddNum ", uid)
			seq.AddNum(uid)
		}
	}

	// no new messages
	if seq.Empty() {
		m.debg.Println("CheckNewMails: No new messages")
		return nil
	}

	cmd, _ = m.imapClient.UIDFetch(seq, "BODY[]")
	postmail := false

	for cmd.InProgress() {
		m.debg.Println("CheckNewMails: cmd in Progress")
		// Wait for the next response (no timeout)
		m.imapClient.Recv(-1)

		// Process command data
		for _, rsp = range cmd.Data {
			msgFields := rsp.MessageInfo().Attrs
			header := imap.AsBytes(msgFields["BODY[]"])
			if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
				m.debg.Println("CheckNewMails:PostMail")
				if err := m.PostMail(msg); err != nil {
					return err
				}
				postmail = true
			}
		}
		cmd.Data = nil
	}

	// Check command completion status
	if rsp, err := cmd.Result(imap.OK); err != nil {
		if err == imap.ErrAborted {
			m.eror.Println("Fetch command aborted")
			return err
		}
		m.eror.Println("Fetch error:", rsp.Info)
		return err
	}

	cmd.Data = nil

	if postmail {
		m.debg.Println("CheckNewMails: Mark all messages with flag \\Seen")

		//Mark all messages seen
		_, err = imap.Wait(m.imapClient.UIDStore(seq, "+FLAGS.SILENT", `\Seen`))
		if err != nil {
			m.eror.Println("Error UIDStore \\Seen")
			return err
		}
	}

	return nil
}
Example #23
0
func main() {
	imap.DefaultLogger = log.New(os.Stdout, "", 0)
	imap.DefaultLogMask = imap.LogConn | imap.LogRaw

	c := Dial(Addr)
	defer func() { ReportOK(c.Logout(30 * time.Second)) }()

	if c.Caps["STARTTLS"] {
		ReportOK(c.StartTLS(nil))
	}

	if c.Caps["ID"] {
		ReportOK(c.ID("name", "goimap"))
	}

	ReportOK(c.Noop())
	ReportOK(Login(c, User, Pass))

	if c.Caps["QUOTA"] {
		ReportOK(c.GetQuotaRoot("INBOX"))
	}

	cmd := ReportOK(c.List("", ""))
	delim := cmd.Data[0].MailboxInfo().Delim

	mbox := MBox + delim + "Demo1"
	if cmd, err := imap.Wait(c.Create(mbox)); err != nil {
		if rsp, ok := err.(imap.ResponseError); ok && rsp.Status == imap.NO {
			ReportOK(c.Delete(mbox))
		}
		ReportOK(c.Create(mbox))
	} else {
		ReportOK(cmd, err)
	}
	ReportOK(c.List("", MBox))
	ReportOK(c.List("", mbox))
	ReportOK(c.Rename(mbox, mbox+"2"))
	ReportOK(c.Rename(mbox+"2", mbox))
	ReportOK(c.Subscribe(mbox))
	ReportOK(c.Unsubscribe(mbox))
	ReportOK(c.Status(mbox))
	ReportOK(c.Delete(mbox))

	ReportOK(c.Create(mbox))
	ReportOK(c.Select(mbox, true))
	ReportOK(c.Close(false))

	msg := []byte(strings.Replace(Msg[1:], "\n", "\r\n", -1))
	ReportOK(c.Append(mbox, nil, nil, imap.NewLiteral(msg)))

	ReportOK(c.Select(mbox, false))
	ReportOK(c.Check())

	fmt.Println(c.Mailbox)

	cmd = ReportOK(c.UIDSearch("SUBJECT", c.Quote("GoIMAP")))
	set, _ := imap.NewSeqSet("")
	set.AddNum(cmd.Data[0].SearchResults()...)

	ReportOK(c.Fetch(set, "FLAGS", "INTERNALDATE", "RFC822.SIZE", "BODY[]"))
	ReportOK(c.UIDStore(set, "+FLAGS.SILENT", imap.NewFlagSet(`\Deleted`)))
	ReportOK(c.Expunge(nil))
	ReportOK(c.UIDSearch("SUBJECT", c.Quote("GoIMAP")))

	fmt.Println(c.Mailbox)

	ReportOK(c.Close(true))
	ReportOK(c.Delete(mbox))
}
Example #24
0
func (emaill *Email) getEmailContentUseIMAP(w rest.ResponseWriter, r *rest.Request) {
	addr := r.FormValue("imapAddr")
	port := r.FormValue("imapPort")
	user := r.FormValue("user")
	pwd := r.FormValue("pwd")
	id := r.FormValue("id")

	address := addr + ":" + port
	log.Printf("get email content use imap %s\n", address)

	var (
		c   *imap.Client
		cmd *imap.Command
		rsp *imap.Response
	)

	// Connect to the server
	c, err := imap.Dial(addr)
	if err != nil {
		log.Printf("dial %s error\n", address)
		return
	}

	// Remember to log out and close the connection when finished
	defer c.Logout(30 * time.Second)

	// Print server greeting (first response in the unilateral server data queue)
	log.Printf("Server says hello:%s", c.Data[0].Info)
	c.Data = nil

	// Enable encryption, if supported by the server
	if c.Caps["STARTTLS"] {
		c.StartTLS(nil)
	}

	// Authenticate
	if c.State() == imap.Login {
		c.Login(user, pwd)
	}

	// List all top-level mailboxes, wait for the command to finish
	cmd, _ = imap.Wait(c.List("", "%"))

	// Print mailbox information
	log.Printf("\nTop-level mailboxes:")
	for _, rsp = range cmd.Data {
		log.Printf("|--%s", rsp.MailboxInfo())
	}

	// Check for new unilateral server data responses
	for _, rsp = range c.Data {
		log.Printf("Server data:%s", rsp)
	}
	c.Data = nil

	// Open a mailbox (synchronous command - no need for imap.Wait)
	c.Select("INBOX", true)
	log.Printf("\nMailbox status:%s\n", c.Mailbox)
	if c.Mailbox == nil {
		resp := EmailJsonResponse{Success: true}
		w.WriteJson(&resp)
		return
	}

	// Fetch the headers of the 10 most recent messages
	set, _ := imap.NewSeqSet("")
	set.Add(id)
	// if c.Mailbox.Messages >= 10 {
	// 	set.AddRange(c.Mailbox.Messages-9, c.Mailbox.Messages) //测试只取最新一封邮件
	// } else {
	// 	set.Add("1:*")
	// }
	cmd, _ = c.Fetch(set, "RFC822.HEADER", "RFC822.TEXT") //指定要获取的内容

	// Process responses while the command is running
	log.Printf("\nget mail [%s] messages:", id)
	for cmd.InProgress() {
		// Wait for the next response (no timeout)
		c.Recv(-1)

		// Process command data
		for _, rsp = range cmd.Data {
			header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"])
			if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
				subject := msg.Header.Get("Subject")
				log.Printf("|--%s", subject)

				realSubject := GetRealSubject(subject)
				log.Printf("in rest_email.go: get real subject")
				log.Printf(realSubject)

				senderAddr := msg.Header.Get("From")
				recverAddrList := msg.Header.Get("To")

				realSenderAddr := GetRealSubject(senderAddr)
				realRecverAddrList := GetRealSubject(recverAddrList)

				body := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.TEXT"])
				//log.Printf("email body: %s", body)
				//realBody  := GetRealBody(string(body))
				headerAndBody := make([]byte, len(header)+len(body))
				copy(headerAndBody, header)
				copy(headerAndBody[len(header):], body)

				msg, _ := mail.ReadMessage(bytes.NewReader(headerAndBody))
				mime, _ := enmime.ParseMIMEBody(msg)
				realBody := mime.Text //如果原始内容为html,会去掉html元素标签
				log.Printf("real body: %s", realBody)

				//获取MIMEPart所有节点内容
				// log.Printf("root ======================")
				// root := mime.Root
				// if root != nil {
				// 	log.Printf(string(root.Content()))
				// 	log.Printf("child==========")
				// 	if child := root.FirstChild(); child != nil {
				// 		log.Printf(string(child.Content()))
				// 	}

				// }

				attachments := mime.Attachments
				log.Printf("attachments len=%d", len(attachments))
				count := len(attachments)
				var attachmentList []Attachment = nil
				var data EmailContent
				if count > 0 {
					attachmentList = make([]Attachment, count)
					for i := 0; i < len(attachments); i++ {
						name := attachments[i].FileName()
						content := attachments[i].Content() //todo encode by base64
						log.Printf("name===%s", name)
						attachmentList[i] = Attachment{Name: name, Body: string(content)}
					}

				}
				data = EmailContent{Subject: realSubject, SenderAddr: realSenderAddr,
					RecverAddrList: realRecverAddrList, Content: realBody,
					Attachments: attachmentList}

				resp := EmailJsonResponse{Success: true, Data: data}
				w.WriteJson(resp)
			}
		}
		cmd.Data = nil

		// Process unilateral server data
		for _, rsp = range c.Data {
			log.Printf("Server data:%s", rsp)
		}
		c.Data = nil
	}

	// Check command completion status
	if rsp, err := cmd.Result(imap.OK); err != nil {
		if err == imap.ErrAborted {
			log.Printf("Fetch command aborted\n")
		} else {
			log.Printf("Fetch error:%s\n", rsp.Info)
		}
	}

}
Example #25
0
func TestLiteral(T *testing.T) {
	t := mock.Server(T,
		`S: * PREAUTH [CAPABILITY IMAP4rev1] Server ready`,
	)
	c, err := t.Dial()
	t.Join(err)

	flags := imap.NewFlagSet(`\Seen`)
	lines := []string{
		"Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)",
		"From: Fred Foobar <*****@*****.**>",
		"Subject: afternoon meeting",
		"To: [email protected]",
		"Message-Id: <*****@*****.**>",
		"MIME-Version: 1.0",
		"Content-Type: TEXT/PLAIN; CHARSET=US-ASCII",
		"",
		"Hello Joe, do you think we can meet at 3:30 tomorrow?",
		"",
	}
	msg := []byte(strings.Join(lines, "\r\n"))
	lit := imap.NewLiteral(msg)

	// Embedded literal
	t.Script(
		`C: A1 APPEND "saved-messages" (\Seen) {310}`,
		`S: + Ready for literal data`,
		`C: `+lines[0],
		`C: `+lines[1],
		`C: `+lines[2],
		`C: `+lines[3],
		`C: `+lines[4],
		`C: `+lines[5],
		`C: `+lines[6],
		`C: `+lines[7],
		`C: `+lines[8],
		`C: `+lines[9],
		`S: A1 OK APPEND completed`,
	)
	_, err = imap.Wait(c.Append("saved-messages", flags, nil, lit))
	t.Join(err)

	// Recv action literal
	t.Script(
		`C: A2 APPEND "saved-messages" (\Seen) {310}`,
		`S: + Ready for literal data`,
		mock.Recv(msg),
		`C: `,
		`S: A2 OK APPEND completed`,
	)
	_, err = imap.Wait(c.Append("saved-messages", flags, nil, lit))
	t.Join(err)

	// Embedded and Send action literals from the server
	t.Script(
		`C: A3 LIST "" "*"`,
		`S: * LIST (\Noselect) "/" {3}`,
		`S: foo`,
		`S: * LIST () "/" {7}`,
		mock.Send("foo/bar"),
		`S: `,
		`S: A3 OK LIST completed`,
	)
	_, err = imap.Wait(c.List("", "*"))
	t.Join(err)
}
Example #26
0
func (c CustomClient) XYZZY() (cmd *imap.Command, err error) {
	if !c.Caps["XYZZY"] {
		return nil, imap.NotAvailableError("XYZZY")
	}
	return imap.Wait(c.Send("XYZZY"))
}
Example #27
0
//use imap to delete a mail
func (email *Email) DeleteEmail(w rest.ResponseWriter, r *rest.Request) {
	log.Printf("delete email...")
	addr := r.FormValue("imapAddr")
	//port := r.FormValue("smtpPort")
	user := r.FormValue("user")
	pwd := r.FormValue("pwd")
	id := r.FormValue("id")

	//check params, return error

	//create imap client
	var (
		c   *imap.Client
		cmd *imap.Command
		rsp *imap.Response
	)

	// Connect to the server
	c, _ = imap.Dial(addr)

	// Remember to log out and close the connection when finished
	defer c.Logout(30 * time.Second)

	// Print server greeting (first response in the unilateral server data queue)
	log.Printf("Server says hello:%s", c.Data[0].Info)
	c.Data = nil

	// Enable encryption, if supported by the server
	if c.Caps["STARTTLS"] {
		c.StartTLS(nil)
	}

	// Authenticate
	if c.State() == imap.Login {
		c.Login(user, pwd)
	}

	// List all top-level mailboxes, wait for the command to finish
	cmd, _ = imap.Wait(c.List("", "%"))

	// Print mailbox information
	log.Printf("\nTop-level mailboxes:")
	for _, rsp = range cmd.Data {
		log.Printf("|--%s", rsp.MailboxInfo())
	}

	// Check for new unilateral server data responses
	for _, rsp = range c.Data {
		log.Printf("Server data:%s", rsp)
	}
	c.Data = nil

	// Open a mailbox (synchronous command - no need for imap.Wait)
	c.Select("INBOX", true)
	log.Printf("\nMailbox status:%s\n", c.Mailbox)
	if c.Mailbox == nil {
		resp := EmailJsonResponse{Success: true}
		w.WriteJson(&resp)
		return
	}

	//use Expunge to delete a mail
	set, _ := imap.NewSeqSet("")
	mid, _ := strconv.Atoi(id)
	set.AddNum(uint32(mid))

	//delete mail
	cmd, err := c.Expunge(set)
	if err != nil {
		log.Printf("%v ", cmd)
	} else {
		log.Printf("delete mail ok")
	}

}
Example #28
0
func ExampleClient() {
	//
	// Note: most of error handling code is omitted for brevity
	//
	var (
		c   *imap.Client
		cmd *imap.Command
		rsp *imap.Response
	)

	// Connect to the server
	c, _ = imap.Dial("imap.example.com")

	// Remember to log out and close the connection when finished
	defer c.Logout(30 * time.Second)

	// Print server greeting (first response in the unilateral server data queue)
	fmt.Println("Server says hello:", c.Data[0].Info)
	c.Data = nil

	// Enable encryption, if supported by the server
	if c.Caps["STARTTLS"] {
		c.StartTLS(nil)
	}

	// Authenticate
	if c.State() == imap.Login {
		c.Login("*****@*****.**", "mysupersecretpassword")
	}

	// List all top-level mailboxes, wait for the command to finish
	cmd, _ = imap.Wait(c.List("", "%"))

	// Print mailbox information
	fmt.Println("\nTop-level mailboxes:")
	for _, rsp = range cmd.Data {
		fmt.Println("|--", rsp.MailboxInfo())
	}

	// Check for new unilateral server data responses
	for _, rsp = range c.Data {
		fmt.Println("Server data:", rsp)
	}
	c.Data = nil

	// Open a mailbox (synchronous command - no need for imap.Wait)
	c.Select("INBOX", true)
	fmt.Print("\nMailbox status:\n", c.Mailbox)

	// Fetch the headers of the 10 most recent messages
	set, _ := imap.NewSeqSet("")
	if c.Mailbox.Messages >= 10 {
		set.AddRange(c.Mailbox.Messages-9, c.Mailbox.Messages)
	} else {
		set.Add("1:*")
	}
	cmd, _ = c.Fetch(set, "RFC822.HEADER")

	// Process responses while the command is running
	fmt.Println("\nMost recent messages:")
	for cmd.InProgress() {
		// Wait for the next response (no timeout)
		c.Recv(-1)

		// Process command data
		for _, rsp = range cmd.Data {
			header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"])
			if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
				fmt.Println("|--", msg.Header.Get("Subject"))
			}
		}
		cmd.Data = nil

		// Process unilateral server data
		for _, rsp = range c.Data {
			fmt.Println("Server data:", rsp)
		}
		c.Data = nil
	}

	// Check command completion status
	if rsp, err := cmd.Result(imap.OK); err != nil {
		if err == imap.ErrAborted {
			fmt.Println("Fetch command aborted")
		} else {
			fmt.Println("Fetch error:", rsp.Info)
		}
	}
}