duanqun7761 2015-08-02 22:49
浏览 193

Golang imap.DialTLS配置示例

I used to be able to connect to port 143 of a mail server like this:

c, err := imap.Dial(mailServer)

The code above connects to port 143 of the mailServer. Now I have a new mail server only accepts port 993. Looking at the Golang imap source code, the function DialTLS will connect to port 993. The signature of DialTLS looks like this:

func DialTLS(addr string, config *tls.Config) (c *Client, err error)

Now I don't know how to construct the *tls.Config. I Googled around, but didn't not find anything really useful. Can someone show me some example how to construct the *tls.Config?

I tried to pass in nil as the second parameter, it compiles, and I didn't get any runtime error. But it seems no new mails were fetched, even I believe there should be.

My fetch mail code looks like this:

// testimap
package main

import (
    "bytes"
    "code.google.com/p/go-imap/go1/imap"
    "fmt"
    "net/mail"
    "time"
)

type Mail struct {
    Subject string
    Body    string
    From    string
    Uid     uint32
}

func FetchMail(lastUid uint32) []*Mail {
    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()
    //
    // 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, err := imap.DialTLS(mailServer, nil)
    if err != nil {
        fmt.Println(err)
    }

    // 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(mailSupportUser, mailSupportPw)
    }

    //// List all top-level mailboxes, wait for the command to finish
    cmd, err = imap.Wait(c.List("", "%"))
    if err != nil {
        fmt.Println(err)
    }
    // Print mailbox information
    //fmt.Println("
Top-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("
Mailbox status:
", c.Mailbox)

    // Fetch the headers of the 10 most recent messages
    set, err := imap.NewSeqSet(fmt.Sprint(lastUid, ":*"))
    if err != nil {
        fmt.Println(err)
    }
    //if c.Mailbox.Messages >= 10 {
    //  set.AddRange(c.Mailbox.Messages-9, c.Mailbox.Messages)
    //} else {
    //  set.Add("1:*")
    //}
    cmd, err = c.UIDFetch(set, "RFC822.HEADER", "RFC822.TEXT")
    if err != nil {
        fmt.Println(err)
    }

    // Process responses while the command is running
    //fmt.Println("
Most recent messages:")
    mails := make([]*Mail, 0, 10)
    for cmd.InProgress() {
        // Wait for the next response (no timeout)
        c.Recv(-1)

        // Process command data
        for _, rsp = range cmd.Data {
            if err != nil {
                fmt.Println(err)
            }
            header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"])
            uid := imap.AsNumber((rsp.MessageInfo().Attrs["UID"]))
            body := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.TEXT"])
            if msg, err := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
                if err != nil {
                    fmt.Println(err)
                }
                mail := &Mail{
                    Subject: msg.Header.Get("Subject"),
                    From:    msg.Header.Get("FROM"),
                    Body:    string(body),
                    Uid:     uid,
                }
                if mail.Uid < lastUid {
                    continue
                }
                mails = append(mails, mail)
            }
        }
        cmd.Data = nil
        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)
        }
    }
    fmt.Println(mails)
    return mails
}
  • 写回答

1条回答 默认 最新

  • drahywu329376 2015-08-03 03:43
    关注

    First off, you should be using the project's GitHub repo as the Google Code project stated development was moving to GitHub due to Google Code shutting down. It's a few commits ahead of the Google Code repo too, so you won't be getting any updates if you don't migrate to the GitHub repo.

    Secondly, looking at the package's demo, passing nil to DialTLS as the TLS client seems to be the proper way to connect with a default TLS client.

    From the information you've given, it seems like it may be an issue with your server accepting connections over that port. I would look into if the port is open to the client you're trying to connect from or if your IMAP server is even accepting TLS connections.

    If you're absolutely sure it's not a server issue after further debugging, I would file an issue on the project's GitHub issue tracker to get help from people who are more familiar with the package, seeing that it's a third party package.

    评论

报告相同问题?

悬赏问题

  • ¥20 sub地址DHCP问题
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突
  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大