Beispiel #1
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
}
Beispiel #2
0
func (i *ImapSession) imapCleanup(folders []string) error {

	c := i.client

	for _, mbox := range folders {
		cmd, err := imap.Wait(c.Select(mbox, false))
		if err != nil {
			fmt.Println("unable to select", mbox, "=>", err, i.client.State())
			continue
		}
		fmt.Println("cleaning up", mbox)
		yesterday := time.Now().Add(-1 * 24 * time.Hour)

		cmd = imapMust(imap.Wait(c.UIDSearch("SEEN BEFORE " + yesterday.Format("02-Jan-2006") + " NOT FLAGGED")))

		toDelete, _ := imap.NewSeqSet("")
		toDelete.AddNum(cmd.Data[0].SearchResults()...)
		if !toDelete.Empty() {
			fmt.Println("deleting...", toDelete)
			if i.isGmail {
				imapMust(imap.Wait(c.UIDStore(toDelete, "X-GM-LABELS", imap.NewFlagSet(`\Trash`))))
			} else {
				imapMust(imap.Wait(c.UIDStore(toDelete, "+FLAGS.SILENT", imap.NewFlagSet(`\Deleted`))))
			}
			imapMust(imap.Wait(c.Expunge(nil)))
		}
	}

	return nil
}
Beispiel #3
0
// checkAndStoreMessages will wait for WorkRequests to come acorss the pipe. When it receives a request, it will search
// the given destination inbox for the message. If it is not found, this method will attempt to pull the messages data
// from fetchRequests and then append it to the destination.
func CheckAndAppendMessages(dstConn *imap.Client, storeRequests chan WorkRequest, fetchRequests chan fetchRequest, wg *sync.WaitGroup) {
	defer wg.Done()

	// noop it every few to keep things alive
	timeout := time.NewTicker(NoopMinutes * time.Minute)
	done := false
	for {
		select {
		case request, ok := <-storeRequests:
			if !ok {
				done = true
				break
			}
			// search for in dst
			cmd, err := imap.Wait(dstConn.UIDSearch([]imap.Field{"HEADER", request.Header, request.Value}))
			if err != nil {
				log.Printf("Unable to search for message (%s): %s. skippin!", request.Value, err.Error())
				continue
			}

			results := cmd.Data[0].SearchResults()
			// if not found, PULL from SRC and STORE in DST
			if len(results) == 0 {
				// only fetch if we dont have data already
				if len(request.Msg.Body) == 0 {
					// build and send fetch request
					response := make(chan MessageData)
					fr := fetchRequest{MessageId: request.Value, UID: request.UID, Response: response}
					fetchRequests <- fr

					// grab response from fetchers
					request.Msg = <-response
				}
				if len(request.Msg.Body) == 0 {
					log.Printf("No data found for from fetch request (%s). giving up", request.Value)
					continue
				}

				err = AppendMessage(dstConn, request.Msg)
				if err != nil {
					log.Printf("Problems appending message to dst: %s. quitting.", err.Error())
					return
				}

			}

		case <-timeout.C:
			imap.Wait(dstConn.Noop())
		}

		if done {
			break
		}
	}

	log.Print("storer complete!")
	return
}
Beispiel #4
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
}
Beispiel #5
0
func checkMessagesExist(srcConn *imap.Client, checkRequests chan checkExistsRequest, wg *sync.WaitGroup) {
	defer wg.Done()
	// get memcache client
	cache := memcache.New(MemcacheServer)

	timeout := time.NewTicker(NoopMinutes * time.Minute)
	done := false
	for {
		select {
		case request, ok := <-checkRequests:
			if !ok {
				done = true
				break
			}
			// check if it exists in src
			// search for in src
			cmd, err := imap.Wait(srcConn.UIDSearch([]imap.Field{"HEADER", "Message-Id", request.MessageId}))
			if err != nil {
				log.Printf("Unable to search source: %s", err.Error())
				request.Response <- true
				continue
			}

			results := cmd.Data[0].SearchResults()
			// if not found, mark for deletion in DST
			found := (len(results) > 0)

			// response with found bool
			request.Response <- found

			// if it doesnt exist, attempt to remove it from memcached
			if !found {
				cache.Delete(request.MessageId)
			}
		case <-timeout.C:
			imap.Wait(srcConn.Noop())
		}

		if done {
			break
		}
	}

}
Beispiel #6
0
// FetchEmails will sit and wait for fetchRequests from the destination workers.
func fetchEmails(conn *imap.Client, requests chan fetchRequest, cache *Cache) {

	// noop every few to keep things alive
	timeout := time.NewTicker(NoopMinutes * time.Minute)
	done := false
	for {
		select {
		case request, ok := <-requests:
			if !ok {
				done = true
				break
			}
			found := true
			// check if the message body is in cache
			data, err := cache.Get(request.MessageId)
			if err != nil {
				found = false
				if err != ErrNotFound {
					log.Printf("problems pulling message data from cache: %s. Pulling message from src...", err.Error())
				}
				data = MessageData{}
			}

			if found {
				log.Print("cache success!")
				request.Response <- data
				continue
			}

			msgData, err := FetchMessage(conn, request.UID)
			if err != nil {
				if err == NotFound {
					log.Printf("No data found for UID: %d", request.UID)
				} else {
					log.Printf("Problems fetching message (%s) data: %s. Passing request and quitting.", request.MessageId, err.Error())
					requests <- request
					return
				}
			}
			request.Response <- msgData

			err = cache.Put(request.MessageId, msgData)
			if err != nil {
				log.Printf("Unable to add message (%s) to cache: %s", request.MessageId, err.Error())
			}

		case <-timeout.C:
			imap.Wait(conn.Noop())
		}

		if done {
			break
		}
	}

}
Beispiel #7
0
func readMessage(message *imap.MessageInfo) {
	set := new(imap.SeqSet)
	set.AddNum(message.Seq)
	cmd, err := imap.Wait(c.Fetch(set, BODY_PART_NAME))
	panicMaybe(err)

	reader, err := messageReader(cmd.Data[0].MessageInfo())
	panicMaybe(err)

	scanner := bufio.NewScanner(reader)
	var lines []string
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	messageBodyStr := strings.Join(lines[:min(len(lines), ui.TermHeight()-2)], "\n")

	if len(messageBodyStr) <= 0 {
		LOG.Printf("Message body was empty or could not be retrieved: +%v\n", err)
		return
	}

	msgBox := ui.NewPar(messageBodyStr)
	msgBox.Border.Label = "Reading Message"
	msgBox.Height = ui.TermHeight()
	msgBox.Width = ui.TermWidth()
	msgBox.Y = 0
	ui.Render(msgBox)

	topLineIndex := 0

	redraw := make(chan bool)

	for {
		select {
		case e := <-ui.EventCh():
			switch e.Key {
			case ui.KeyArrowDown:
				topLineIndex = max(0, min(
					len(lines)-msgBox.Height/2,
					topLineIndex+1))
				go func() { redraw <- true }()
			case ui.KeyArrowUp:
				topLineIndex = max(0, topLineIndex-1)
				go func() { redraw <- true }()
			case ui.KeyEsc:
				// back to "list messages"
				return
			}
		case <-redraw:
			messageBodyStr = strings.Join(lines[topLineIndex+1:], "\n")
			msgBox.Text = messageBodyStr
			ui.Render(msgBox)
		}
	}
}
Beispiel #8
0
func GetAllMessages(conn *imap.Client) (*imap.Command, error) {
	// get headers and UID for ALL message in src inbox...
	allMsgs, _ := imap.NewSeqSet("")
	allMsgs.Add("1:*")
	cmd, err := imap.Wait(conn.Fetch(allMsgs, "RFC822.HEADER", "UID"))
	if err != nil {
		return &imap.Command{}, err
	}

	return cmd, nil
}
Beispiel #9
0
func ResetConnection(conn *imap.Client, readOnly bool) error {
	// dont check for error because its possible it's already closed.
	conn.Close(!readOnly)

	_, err := imap.Wait(conn.Select("INBOX", readOnly))
	if err != nil {
		return err
	}

	return nil
}
Beispiel #10
0
func checkAndPurgeMessages(conn *imap.Client, requests chan WorkRequest, checkRequests chan checkExistsRequest, wg *sync.WaitGroup) {
	defer wg.Done()

	timeout := time.NewTicker(NoopMinutes * time.Minute)
	done := false
	for {
		select {
		case request, ok := <-requests:
			if !ok {
				done = true
				break
			}
			// check and wait for response
			response := make(chan bool)
			cr := checkExistsRequest{UID: request.UID, MessageId: request.Value, Response: response}
			checkRequests <- cr

			// if response is false (does not exist), flag as Deleted
			if exists := <-response; !exists {
				log.Printf("not found in src. marking for deletion: %s", request.Value)
				err := AddDeletedFlag(conn, request.UID)
				if err != nil {
					log.Printf("Problems removing message from dst: %s", err.Error())
				}
			}
		case <-timeout.C:
			imap.Wait(conn.Noop())
		}

		if done {
			break
		}
	}

	log.Printf("expunging...")
	// expunge at the end
	allMsgs, _ := imap.NewSeqSet("")
	allMsgs.Add("1:*")
	imap.Wait(conn.Expunge(allMsgs))
	log.Printf("expunge complete.")
}
Beispiel #11
0
func (i *ImapSession) Append(folder string, extraCopies []string, msg io.Reader) error {
	c := i.client

	mbox := folder

	buf := new(bytes.Buffer)
	buf.ReadFrom(msg)

	now := time.Now()
	cmd, err := imap.Wait(c.Append(mbox, nil, &now, imap.NewLiteral(buf.Bytes())))
	if err != nil {
		fmt.Println(err)
		return err
	}

	rsp, err := cmd.Result(imap.OK)
	if err != nil {
		fmt.Println(err)
		return err
	}

	uid := imap.AsNumber(rsp.Fields[len(rsp.Fields)-1])

	set, _ := imap.NewSeqSet("")
	set.AddNum(uid)

	imapMust(imap.Wait(c.Select(mbox, false)))

	for _, mb := range extraCopies {
		if i.isGmail {
			imapMust(imap.Wait(c.UIDStore(set, "X-GM-LABELS", imap.NewFlagSet(mb))))
		} else {
			imapMust(c.UIDCopy(set, mb))
		}
	}

	return nil
}
Beispiel #12
0
func (i *ImapSession) CreateFolder(folder string) error {
	c := i.client

	mbox := folder

	if _, err := imap.Wait(c.Create(mbox)); err != nil {
		if rsp, ok := err.(imap.ResponseError); ok && rsp.Status == imap.NO {
			return nil
		} else {
			return err
		}
	}

	return nil
}
Beispiel #13
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
}
Beispiel #14
0
func GetConnection(info InboxInfo, readOnly bool) (*imap.Client, error) {
	conn, err := imap.DialTLS(info.Host, new(tls.Config))
	if err != nil {
		return nil, err
	}

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

	_, err = imap.Wait(conn.Select("INBOX", readOnly))
	if err != nil {
		return nil, err
	}

	return conn, nil
}
Beispiel #15
0
func FetchMessage(conn *imap.Client, messageUID uint32) (msg MessageData, err error) {
	seq, _ := imap.NewSeqSet("")
	seq.AddNum(messageUID)
	var cmd *imap.Command
	cmd, err = imap.Wait(conn.UIDFetch(seq, "INTERNALDATE", "BODY[]", "UID", "RFC822.HEADER"))
	if err != nil {
		log.Printf("Unable to fetch message (%d): %s", messageUID, err.Error())
		return
	}

	if len(cmd.Data) == 0 {
		log.Printf("Unable to fetch message (%d) from src: NO DATA", messageUID)
		return msg, NotFound
	}

	msgFields := cmd.Data[0].MessageInfo().Attrs
	msg = MessageData{InternalDate: imap.AsDateTime(msgFields["INTERNALDATE"]), Body: imap.AsBytes(msgFields["BODY[]"])}
	return msg, nil
}
Beispiel #16
0
func GetUIDs(mbox string, client *imap.Client) ([]uint32, error) {

	uids := make([]uint32, 0)

	cmd, err := client.Select(mbox, true)
	if err != nil {
		return uids, err
	}

	//== Get UIDS of all messages
	cmd, err = imap.Wait(client.UIDSearch("", "ALL"))
	if err != nil {
		return uids, err
	}

	for idx := range cmd.Data {
		for _, uid := range cmd.Data[idx].SearchResults() {
			uids = append(uids, uid)
		}
	}
	return uids, nil

}
Beispiel #17
0
// getNextUID will grab the next message UID from the inbox. Client.Mailbox.UIDNext is cached so we can't use it.
func getNextUID(conn *imap.Client) (uint32, error) {
	cmd, err := imap.Wait(conn.Status("INBOX", "UIDNEXT"))
	if err != nil {
		return 0, err
	}

	if len(cmd.Data) == 0 {
		return 0, errors.New("no data returned!")
	}

	var status *imap.MailboxStatus
	for _, resp := range cmd.Data {
		switch resp.Type {
		case imap.Data:
			status = resp.MailboxStatus()
			if status != nil {
				break
			}
		}
	}

	return status.UIDNext, nil
}
Beispiel #18
0
// geet all the top-level mailboxes in the server, and return them
func (s *Server) GetMailboxes() (boxes []*Mailbox, err error) {
	c, err := s.Connect()
	if err != nil {
		return
	}

	// fetch data synchronously
	cmd, err := imap.Wait(c.List("", "%"))
	if err != nil {
		return
	}

	boxes = make([]*Mailbox, len(cmd.Data))

	for i, rsp := range cmd.Data {
		info := rsp.MailboxInfo()
		mbox := NewMailbox(info.Name, s)
		boxes[i] = mbox
		s.Mailboxes[mbox.Name] = mbox
	}

	return boxes, nil
}
Beispiel #19
0
//= Return list of IMAP folders
func GetFolders(client *imap.Client) ([]*Folder, error) {

	folders := make([]*Folder, 0)

	cmd, err := imap.Wait(client.List("", "*"))
	if err != nil {
		return folders, err
	}

	for idx := range cmd.Data {
		info := cmd.Data[idx].MailboxInfo()
		fol := new(Folder)
		fol.Name = info.Name
		for flag, boo := range info.Attrs {
			fmt.Println(info.Name, boo, flag)
			if info.Name == "INBOX" && boo {
				fol.Type = "inbox"

			} else if flag == "\\Junk" && boo {
				fol.Type = "junk"

			} else if flag == "\\Trash" && boo {
				fol.Type = "trash"

			} else if flag == "\\Sent" && boo {
				fol.Type = "sent"

			} else if flag == "\\Drafts" && boo {
				fol.Type = "drafts"
			}

		}
		folders = append(folders, fol)
	}

	return folders, nil
}
Beispiel #20
0
// messages are usually created with just header information
// this method downloads the actual body of the message from the server,
// optionally marking the message as '\Seen', in IMAP terms.
func (m *Email) Body(setRead bool) (body []byte, err error) {
	// cache
	if m.bodyData != nil {
		return m.bodyData, nil
	}

	// what will our FETCH request?
	var requestType string
	if setRead {
		requestType = "BODY[TEXT]"
	} else {
		requestType = "BODY.PEEK[TEXT]"
	}

	cmd, err := m.RetrieveRaw(requestType)
	cmd, err = imap.Wait(cmd, err)
	if err != nil {
		return
	}

	info := cmd.Data[0].MessageInfo()
	m.bodyData = imap.AsBytes(info.Attrs["BODY[TEXT]"])
	return m.bodyData, nil
}
Beispiel #21
0
func connectNet(user string) {
	netTimeout := time.Second * 30
	cl, err := imap.DialTLS("imap.gmail.com", nil)
	if err != nil {
		log.Println(err)
		time.Sleep(netTimeout)
		return
	}
	defer cl.Logout(-1)
	log.Println("server says hello:", cl.Data[0].Info)
	cl.Data = nil
	log.Println("logging in")
	if cl.State() == imap.Login {
		_, err = cl.Login(user+"@gmail.com", "PASSHERE")
		if err != nil {
			log.Println(err)
			time.Sleep(netTimeout)
			return
		}
	}
	log.Println("logged in")
	log.Println("selecting INBOX")
	_, err = cl.Select("INBOX", false)
	if err != nil {
		log.Println(err)
		time.Sleep(netTimeout)
		return
	}
	log.Println("selected INBOX")
	set, _ := imap.NewSeqSet("")
searchLoop:
	for {
		var successCounter int
		conTimeout := 5
		log.Println("searching INBOX")
		cmd, err := imap.Wait(cl.Search("SUBJECT \"Confirm your email\""))
		if err != nil {
			log.Println(err)
			break searchLoop
		}
		searchResults := cmd.Data[0].SearchResults()
		if searchResults == nil {
			log.Println("no email[s] found")
			time.Sleep(time.Second * 5)
			break searchLoop
		} else {
			log.Println("found", len(searchResults), "emails to spoof, results:", searchResults)
			set.AddNum(searchResults...)
		}
		var rsp *imap.Response
		link := regexp.MustCompile(`https:=\r\n\/\/invites.oneplus.net\/confirm\/[0-9A-Z]*.`)
		var UIDCounter int
		log.Println("beginning spoof confirmation loop")
		cmd, err = cl.Fetch(set, "RFC822")
		if err != nil {
			log.Println(err)
			break searchLoop
		}
		setDone, _ := imap.NewSeqSet("")
	getMailLoop:
		for cmd.InProgress() {
			cl.Recv(-1)
			for _, rsp = range cmd.Data {
				message := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822"])
				if msg, err := mail.ReadMessage(bytes.NewReader(message)); msg != nil {
					log.Println("current conTimeout", conTimeout)
					body, err := ioutil.ReadAll(msg.Body)
					if err != nil {
						log.Println(err)
						break searchLoop
					}
					linkRawM := link.FindSubmatch(body)
					var linkRaw []byte
					if len(linkRawM) > 0 {
						linkRaw = linkRawM[0]
					} else {
						log.Println("found nolink mail")
						continue getMailLoop
					}
					log.Println(string(linkRaw))
					url, err := url.Parse(string(linkRaw[:6]) + string(linkRaw[9:]))
					if err != nil {
						log.Println(err)
						break searchLoop
					}
					log.Println(url)
					req := confirmURL.ReplaceAll(reqTemplate, []byte(url.Path)[:len(url.Path)-1])
					for {
						log.Println("attempting to spoof confirmation for", searchResults[UIDCounter])
						c, err := tls.Dial("tcp", url.Host+":443", nil)
						if err != nil {
							log.Println(err)
							break searchLoop
						}
						_, err = c.Write(req)
						if err != nil {
							log.Println(err)
							break searchLoop
						}
						resp, err := http.ReadResponse(bufio.NewReader(c), nil)
						if err != nil {
							log.Println(err)
							break searchLoop
						}
						if resp.StatusCode == 302 {
							redirectReg := regexp.MustCompile(`https:\/\/oneplus\.net\/invites\?kid=[0-9A-Z]*`)
							redirectURL, err := resp.Location()
							if err != nil {
								log.Println(err)
								break searchLoop
							}
							log.Println(resp.Location())
							if redirectReg.MatchString(redirectURL.String()) {
								log.Println("successfully spoofed confirmation for", searchResults[UIDCounter])
								setDone.AddNum(searchResults[UIDCounter])
								UIDCounter++
								if successCounter == 10 {
									conTimeout--
									successCounter = 0
								}
								break
							} else {
								log.Println("server trying to migitate spoofing")
								conTimeout++
								successCounter = 0
							}
						} else {
							log.Println("gg rip hamsters")
							conTimeout++
							successCounter = 0
						}
						time.Sleep(time.Second * time.Duration(conTimeout))
					}
				} else {
					log.Println(err)
				}
			}
			time.Sleep(time.Second * time.Duration(conTimeout))
			cmd.Data = nil
		}
		log.Println("deleting mail", setDone)
		_, err = imap.Wait(cl.Store(setDone, "+FLAGS", "\\DELETED"))
		if err != nil {
			log.Println(err)
			break searchLoop
		}
		_, err = imap.Wait(cl.Expunge(nil))
		if err != nil {
			log.Println(err)
			break searchLoop
		}
	}
}
Beispiel #22
0
func main() {
	// Source: https://godoc.org/code.google.com/p/go-imap/go1/imap#example-Client
	// Note: most of error handling code is omitted for brevity
	//

	// Connect to the server
	c, _ = imap.DialTLS(IMAP_SERVER, nil)

	// 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(USERNAME, PASSWORD)
	}

	// 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-19, c.Mailbox.Messages)
	} else {
		set.Add("1:*")
	}
	cmd, _ = imap.Wait(c.Fetch(set, HEADER_PART_NAME))

	messages := make([]*imap.MessageInfo, 0, 0)
	for _, rsp = range cmd.Data {
		// May not be necessary to check for nil here.
		if msg := rsp.MessageInfo(); msg != nil {
			messages = append(messages, msg)
		}
	}
	listMessages(messages)

	// // 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[HEADER_PART_NAME])
	// 		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)
	// 	}
	// }

	//	render()
}
Beispiel #23
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)
		}
	}
}
Beispiel #24
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))
}
Beispiel #25
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"))
}
Beispiel #26
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)
}
Beispiel #27
0
func main() {
	flag.Parse()
	email, password := getCredentials()

	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt, os.Kill)
	go func() {
		<-quit
		os.Exit(0)
	}()

	connect := func(server string) (c *imap.Client, err error) {
		c, err = imap.DialTLS(server, &tls.Config{})
		if err != nil {
			return
		}

		_, err = c.Auth(imap.PlainAuth(email, password, ""))
		if err != nil {
			return
		}

		log.Println("Successfully authed")

		cmd, err := c.Select(*mailbox, true)
		if err != nil {
			log.Println("Error selecting mailbox: ", err)
			return
		}
		_, err = cmd.Result(imap.OK)
		if err != nil {
			return
		}

		log.Println("Successfully selected ", *mailbox)

		_, err = c.Idle()
		if err != nil {
			return
		}

		log.Println("Starting idle...")
		c.Data = nil

		return
	}

loop:
	for {
		if err := cmd(); err != nil {
			log.Printf("Error running sync on new loop: %s\n", err)
			continue
		}

		c, err := connect("imap.gmail.com")
		if err != nil {
			continue
		}

		wait := true
		for wait {
			err = c.Recv(15 * time.Minute)
			switch err {
			case nil:
				fallthrough
			case io.EOF:
				// We received content from server -- sync mails
				wait = false
			case imap.ErrTimeout:
				// after the timeout, wakeup the connection
				if _, err := c.IdleTerm(); err != nil {
					log.Println("Error finishing idle:: ", err)
					continue loop
				}
				if _, err := imap.Wait(c.Noop()); err != nil {
					log.Println("Error nooping: ", err)
					continue loop
				}
				log.Println("Keeping it alive !")
				if _, err := c.Idle(); err != nil {
					log.Println("Error re-idling: ", err)
					continue loop
				}
			default:
				log.Println("Error while receiving content: ", err)
				continue loop
			}
		}

		for _, rsp := range c.Data {
			if rsp.Label == "EXISTS" {
				log.Println("New message, running sync...")
				if err := cmd(); err != nil {
					log.Printf("Error running sync: %s\n", err)
				}
				log.Println("Ran sync")
			}
		}

		c.Data = nil
	}
}
Beispiel #28
0
func AppendMessage(conn *imap.Client, messageData MessageData) error {
	_, err := imap.Wait(conn.Append("INBOX", imap.NewFlagSet("UnSeen"), &messageData.InternalDate, imap.NewLiteral(messageData.Body)))
	return err
}
Beispiel #29
0
func GetMessage(folder, uid string, client *imap.Client) (messag *Message, e error) {

	cmd, err := client.Select(folder, true)
	if err != nil {
		return nil, err
	}

	uidlist, _ := imap.NewSeqSet(uid)
	//uidlist.Add(uid)

	fmt.Println("get_mess", folder, uid)
	mess := new(Message)
	mess.Folder = folder

	cmd, err = imap.Wait(client.UIDFetch(uidlist, "FLAGS", "INTERNALDATE", "RFC822.SIZE", "RFC822")) //  "RFC822.HEADER",  "BODY.PEEK[TEXT]") )
	if err != nil {
		return mess, err
	}
	fmt.Println(len(cmd.Data), cmd.Data)
	rsp := cmd.Data[0]
	minfo := rsp.MessageInfo()

	mess.Uid = minfo.UID

	msg, _ := mail.ReadMessage(bytes.NewReader(imap.AsBytes(minfo.Attrs["RFC822"])))
	mime, mime_err := enmime.ParseMIMEBody(msg)

	for flag, boo := range minfo.Flags {
		if flag == "\\Seen" && boo {
			mess.Seen = true
		}
		if flag == "\\Flagged" && boo {
			mess.Flagged = true
		}
	}
	/*
		bites := imap.AsBytes(minfo.Attrs["RFC822"])
		msg, msg_err := mail.ReadMessage(bytes.NewReader(bites))
		if msg_err != nil {
			return mess, msg_err
		}
	*/

	//fmt.Println(msg.Header.Get("Content-type"))
	//fmt.Println(msg.Header.Get("To"))
	//fmt.Println(msg.Header.Get("Delivered-To"))

	// From
	from, fro_err := mail.ParseAddress(msg.Header.Get("From"))
	if fro_err != nil {
		fmt.Println("address ettot")
	} else {
		mess.FromName = from.Name
		mess.FromEmail = from.Address
	}

	//for i, m := range minfo.Attrs {

	//fmt.Println(i,m)
	//}
	// Date
	dat := imap.AsDateTime(minfo.Attrs["INTERNALDATE"])
	mess.Date = dat.Format("2006-01-02 15:04:05")

	mess.Subject = msg.Header.Get("Subject")
	mess.ContentType = msg.Header.Get("Content-Type")
	//fmt.Println("body=", cmd.Data[0].String)

	//bodyb := imap.AsBytes(minfo.Attrs["BODY[TEXT]"])
	//bb := 	bytes.NewReader(bytes.NewReader(header + bodyb))

	//fmt.Println("bodyb=", string(msg.Body))

	//fmt.Printf("----\n%v\n", mime.Html == nil)
	//mess.Body = mime.Text
	if mime_err != nil {
		fmt.Println("err=", mime_err, mime)
	}
	//*/
	//fmt.Println("body=", body)

	mess.BodyText = mime.Text
	mess.BodyHtml = mime.Html //imap.AsString(minfo.Attrs["RFC822"])

	return mess, nil

}