Home > OS >  emersion/go-imap - imap.FetchRFC822: invalid memory address or nil pointer dereference
emersion/go-imap - imap.FetchRFC822: invalid memory address or nil pointer dereference

Time:12-23

I am trying to fetch all E-Mails from the Server with the following source Code (this function is called in the main module):

package internal

import (
    "fmt"
    "io"
    "io/ioutil"
    "log"

    "github.com/emersion/go-imap"
    "github.com/emersion/go-imap/client"
    "github.com/emersion/go-message"
)

func FetchEMail(server string, username string, password string) error {
    //Connect to Server
    log.Println("Connecting to server...")

    c, err := client.DialTLS(server, nil)
    log.Println("Connected to "   server)
    defer c.Logout()

    //check if connection successful
    if err != nil {
        log.Println("In connection Error")
        return err
    }

    //err = nil

    //Login
    log.Println("Logging in...")
    err = c.Login(username, password)
    log.Println("Logged in as "   username)

    //check if login successful
    if err != nil {
        log.Println("In login Error")
        return err
    }

    //Select INBOX
    log.Println("Selecting INBOX...")
    mbox, err := c.Select("INBOX", false)
    log.Println("Selected INBOX")

    //check if select successful
    if err != nil {
        return err
    }

    //Fetch all messages
    log.Println("Fetching all messages...")
    seqset := new(imap.SeqSet)
    seqset.AddRange(1, mbox.Messages)
    items := []imap.FetchItem{imap.FetchRFC822}
    messages := make(chan *imap.Message, 10)
    done := make(chan error, 1)
    go func() {
        done <- c.Fetch(seqset, items, messages)
    }()

    //check if fetch successful
    if err := <-done; err != nil {
        log.Println("In fetch Error")
        return err
    }

    log.Println("Run Successful - Terminating...")
    return nil
}

This results into the following error:

panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x5ee505]

goroutine 1 [running]:

I already have tried imap.FetchEvelope() which works, but for some reason imap.FetchRFC822 does not work.

My main goal is to export all E-Mail attachments (.gz, .zip, ...) from all E-Mails, that is why I need the whole E-Mail, not only the Envelope.

CodePudding user response:

I think the issue was in this line items := []imap.FetchItem{imap.FetchRFC822}.
First, let's clarify what the FetchItem type is. This represents the different parts of an email that can be fetched (envelope, body, UID, flags, and so on).
Then, let's talk about the Fetch method. It expects a slice of imap.FetchItem passed in. It retrieves from the emails all of the parts specified by the slice.
So what fixes your issue is replacing this line with items := []imap.FetchItem{imap.FetchRFC822, imap.FetchEnvelope}.
I fixed and tested your program as you can see from the code snippet below:

package main

import (
    "fmt"
    "log"

    "github.com/emersion/go-imap"
    "github.com/emersion/go-imap/client"
)

func FetchEMail(server string, username string, password string) error {
    // Connect to Server
    log.Println("Connecting to server...")

    c, err := client.Dial(server)
    log.Println("Connected to "   server)
    defer c.Logout()

    // check if connection successful
    if err != nil {
        log.Println("In connection Error")
        return err
    }

    // Login
    log.Println("Logging in...")
    err = c.Login(username, password)
    log.Println("Logged in as "   username)

    // check if login successful
    if err != nil {
        log.Println("In login Error")
        return err
    }

    // Select INBOX
    log.Println("Selecting INBOX...")
    mbox, err := c.Select("INBOX", false)
    log.Println("Selected INBOX")

    // check if select successful
    if err != nil {
        return err
    }

    // Fetch all messages
    log.Println("Fetching all messages...")
    seqset := new(imap.SeqSet)
    seqset.AddRange(1, mbox.Messages)
    items := []imap.FetchItem{imap.FetchRFC822, imap.FetchEnvelope}
    messages := make(chan *imap.Message, 10)
    done := make(chan error, 1)
    go func() {
        done <- c.Fetch(seqset, items, messages)
    }()

    for msg := range messages {
        fmt.Printf("suject: %v\n", msg.Envelope.Subject)
    }

    // check if fetch successful
    if err := <-done; err != nil {
        log.Println("In fetch Error")
        return err
    }

    log.Println("Run Successful - Terminating...")
    return nil
}

func main() {
    err := FetchEMail("xxxxxxx", "xxxxx", "xxxxx")
    if err != nil {
        panic(err)
    }
}

Near the end, I added a for to print the subject of the retrieved emails. Here, you can replace the code with your own logic. The nil pointer dereference error disappears.
Let me know if this solves your issue!

  • Related