Skip to content

Instantly share code, notes, and snippets.

@ewalk153
Created August 18, 2014 22:19
Show Gist options
  • Select an option

  • Save ewalk153/5d6ab06e3e0bae9d442d to your computer and use it in GitHub Desktop.

Select an option

Save ewalk153/5d6ab06e3e0bae9d442d to your computer and use it in GitHub Desktop.
parse MBOX file format for attachments
package main
import (
"bufio"
"bytes"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
// "log"
"mime"
"mime/multipart"
"net/mail"
"os"
"path"
"strings"
)
func check(e error) {
if e != nil {
panic(e)
}
}
func blocks(f io.Reader, match string) [][]byte {
r := bufio.NewReader(f)
var b bytes.Buffer
lx := [][]byte{}
for n := 0; ; n++ {
l, err := r.ReadBytes('\n')
if err != nil {
break
}
if strings.Contains(string(l), match) {
if n > 0 {
lx = append(lx, b.Bytes())
}
b = bytes.Buffer{}
}
b.Write(l)
}
lx = append(lx, b.Bytes())
return lx
}
func parseFiles(b []byte) {
m, err := mail.ReadMessage(bytes.NewReader(b))
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r, m.Header.Get("From"))
}
}()
check(err)
from := m.Header.Get("From")
d, err := m.Header.Date()
check(err)
dir := d.Format("20060102") + from
os.Mkdir(dir, 0777)
mediaType, params, err := mime.ParseMediaType(m.Header.Get("Content-Type"))
check(err)
if strings.HasPrefix(mediaType, "multipart/") {
mr := multipart.NewReader(m.Body, params["boundary"])
for i := 0; ; i++ {
p, err := mr.NextPart()
if err == io.EOF {
return
}
if err != nil {
// log.Fatal(err)
panic(err)
}
slurp, err := ioutil.ReadAll(p)
if err != nil {
// log.Fatal(err)
panic(err)
}
name := p.FileName()
data := slurp
if name == "" {
name = fmt.Sprintf("no-name-%d.html", i)
} else {
data, err = base64.StdEncoding.DecodeString(string(slurp))
if err != nil {
// fmt.Println("error:", err)
panic(err)
return
}
}
x, err := os.Create(path.Join(dir, name))
if err != nil {
// fmt.Println("error:", err)
panic(err)
return
}
x.Write(data)
x.Close()
}
}
}
func main() {
f, err := os.Open(os.Args[1])
check(err)
defer f.Close()
for _, l := range blocks(f, "From ") {
parseFiles(l)
// fmt.Println(i)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment