]> fluffbu.de Git - imapper-go.git/blame_incremental - imapper.go
hehehe
[imapper-go.git] / imapper.go
... / ...
CommitLineData
1package main
2
3import (
4 "bufio"
5 "crypto/tls"
6 "fmt"
7 "net"
8 "regexp"
9 "strings"
10)
11
12func main() {
13 // Replace with your server details and credentials
14 server := "mail.fluffbu.de:993"
15 username := "kek@fluffbu.de"
16 password := ""
17 mailbox := "sorter"
18 moveToFolder := "Archive"
19
20 // Create TLS connection
21 conn, err := tls.Dial("tcp", server, &tls.Config{})
22 if err != nil {
23 fmt.Println("Error connecting:", err)
24 return
25 }
26 defer conn.Close()
27
28 reader := bufio.NewReader(conn)
29
30 // Read server greeting
31 initialResponse(reader)
32
33 // Login to the server
34 writeAndRead(reader, conn, "a1 LOGIN "+username+" "+password)
35
36 // Select the mailbox
37 writeAndRead(reader, conn, "a1 SELECT "+mailbox)
38
39 // Fetch email IDs (UIDs)
40 messageUIDs := fetchMessageIDs(reader, conn)
41
42 // Move the emails to the target folder
43 moveEmails(reader, conn, messageUIDs, moveToFolder)
44
45 // Expunge deleted messages and logout
46 writeAndRead(reader, conn, "a1 EXPUNGE + LOGOUT")
47}
48
49// initialResponse handles the server greeting
50func initialResponse(reader *bufio.Reader) {
51greetingloop:
52 for {
53 line, err := reader.ReadString('\n')
54 if err != nil {
55 fmt.Println("Error reading greeting:", err)
56 return
57 }
58 fmt.Print("Server Greeting: " + line)
59
60 // Exit loop when server is ready (usually contains "OK")
61 if strings.Contains(line, "OK") {
62 break greetingloop
63 }
64 }
65}
66
67// fetchMessageIDs fetches the UID of all messages in the mailbox and returns them as a slice of UIDs
68func fetchMessageIDs(reader *bufio.Reader, conn net.Conn) []string {
69 // Fetch UIDs for all messages (1:*)
70 fmt.Println("Fetching message UIDs:")
71 // writeAndRead(reader, conn, "a1 UID FETCH 1:* (UID)")
72 fmt.Fprintf(conn, "a1 UID FETCH 1:* (UID)"+"\r\n")
73
74 var uids []string
75 re := regexp.MustCompile(`UID\s+(\d+)`)
76 readingUIDs := false
77
78stringread:
79 for {
80 line, err := reader.ReadString('\n')
81 if err != nil {
82 fmt.Println("Error reading:", err)
83 break stringread
84 }
85
86 // Start reading UIDs when we see the first UID line
87 if strings.Contains(line, "FETCH (UID") {
88 readingUIDs = true
89 }
90
91 // Parse UID and collect it in the slice
92 if readingUIDs {
93 match := re.FindStringSubmatch(line)
94 if len(match) > 1 {
95 uid := match[1]
96 fmt.Println("Message UID:", uid)
97 uids = append(uids, uid)
98 }
99 }
100
101 // Stop reading when we get an "OK", "NO", or "BAD" response
102 if strings.HasPrefix(line, "a1 OK") || strings.HasPrefix(line, "NO") || strings.HasPrefix(line, "BAD") {
103 break stringread
104 }
105 }
106
107 return uids
108}
109
110// moveEmails moves emails with the given UIDs to the target folder and marks them for deletion in the original folder
111func moveEmails(reader *bufio.Reader, conn net.Conn, uids []string, moveToFolder string) {
112 if len(uids) == 0 {
113 fmt.Println("No messages to move.")
114 return
115 }
116
117 // Combine UIDs into a single string
118 uidList := strings.Join(uids, ",")
119
120 // Copy the messages to the target folder
121 fmt.Println("Moving messages to folder:", moveToFolder)
122 writeAndRead(reader, conn, "a1 UID COPY "+uidList+" "+moveToFolder)
123
124 // Mark the messages as deleted in the original folder
125 writeAndRead(reader, conn, "a1 UID STORE "+uidList+" +FLAGS.SILENT (\\Deleted)")
126}
127
128func writeAndRead(reader *bufio.Reader, conn net.Conn, command string) error {
129 // Write the command to the IMAP server
130 fmt.Println("C: " + command)
131 fmt.Fprintf(conn, command+"\r\n")
132
133 // Read the response
134responseloop:
135 for {
136 line, err := reader.ReadString('\n')
137 if err != nil {
138 fmt.Println("Error reading:", err)
139 return err
140 }
141
142 // Print the server's response line
143 fmt.Print("S: " + line)
144
145 // Stop reading when we get an "OK", "NO", or "BAD" response
146 if strings.Contains(line, "a1 OK") || strings.Contains(line, "a1 NO") || strings.Contains(line, "BAD") {
147 break responseloop
148 }
149 }
150
151 return nil
152}