Golang imap.DialTLS Config example

huangapple go评论89阅读模式
英文:

Golang imap.DialTLS Config example

问题

我曾经可以像这样连接到邮件服务器的143端口:

c, err := imap.Dial(mailServer)

上面的代码连接到mailServer143端口。现在我有一个新的邮件服务器,只接受993端口。查看Golang的imap源代码,函数DialTLS将连接到993端口。DialTLS的签名如下:

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

现在我不知道如何构建*tls.Config。我在Google上搜索了一下,但没有找到真正有用的东西。有人可以给我展示一些如何构建*tls.Config的示例吗?

我尝试将nil作为第二个参数传递进去,它可以编译通过,并且我没有收到任何运行时错误。但是似乎没有获取到新的邮件,即使我相信应该有新的邮件。

我的获取邮件代码如下:

// 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("\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, 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("\nMost 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
}
英文:

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 (
&quot;bytes&quot;
&quot;code.google.com/p/go-imap/go1/imap&quot;
&quot;fmt&quot;
&quot;net/mail&quot;
&quot;time&quot;
)
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(&quot;Server says hello:&quot;, c.Data[0].Info)
c.Data = nil
// Enable encryption, if supported by the server
if c.Caps[&quot;STARTTLS&quot;] {
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(&quot;&quot;, &quot;%&quot;))
if err != nil {
fmt.Println(err)
}
// Print mailbox information
//fmt.Println(&quot;\nTop-level mailboxes:&quot;)
//for _, rsp = range cmd.Data {
//	fmt.Println(&quot;|--&quot;, rsp.MailboxInfo())
//}
// Check for new unilateral server data responses
//for _, rsp = range c.Data {
//	fmt.Println(&quot;Server data:&quot;, rsp)
//}
c.Data = nil
// Open a mailbox (synchronous command - no need for imap.Wait)
c.Select(&quot;INBOX&quot;, true)
//fmt.Print(&quot;\nMailbox status:\n&quot;, c.Mailbox)
// Fetch the headers of the 10 most recent messages
set, err := imap.NewSeqSet(fmt.Sprint(lastUid, &quot;:*&quot;))
if err != nil {
fmt.Println(err)
}
//if c.Mailbox.Messages &gt;= 10 {
//	set.AddRange(c.Mailbox.Messages-9, c.Mailbox.Messages)
//} else {
//	set.Add(&quot;1:*&quot;)
//}
cmd, err = c.UIDFetch(set, &quot;RFC822.HEADER&quot;, &quot;RFC822.TEXT&quot;)
if err != nil {
fmt.Println(err)
}
// Process responses while the command is running
//fmt.Println(&quot;\nMost recent messages:&quot;)
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[&quot;RFC822.HEADER&quot;])
uid := imap.AsNumber((rsp.MessageInfo().Attrs[&quot;UID&quot;]))
body := imap.AsBytes(rsp.MessageInfo().Attrs[&quot;RFC822.TEXT&quot;])
if msg, err := mail.ReadMessage(bytes.NewReader(header)); msg != nil {
if err != nil {
fmt.Println(err)
}
mail := &amp;Mail{
Subject: msg.Header.Get(&quot;Subject&quot;),
From:    msg.Header.Get(&quot;FROM&quot;),
Body:    string(body),
Uid:     uid,
}
if mail.Uid &lt; 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(&quot;Fetch command aborted&quot;)
} else {
fmt.Println(&quot;Fetch error:&quot;, rsp.Info)
}
}
fmt.Println(mails)
return mails
}

答案1

得分: 5

首先,你应该使用项目的GitHub存储库,因为Google Code项目已经宣布将开发转移到GitHub,因为Google Code即将关闭。GitHub存储库还领先于Google Code存储库几个提交,所以如果你不迁移到GitHub存储库,就不会收到任何更新。

其次,从包的演示中可以看出,将nil传递给DialTLS作为TLS客户端似乎是使用默认TLS客户端连接的正确方式。

根据你提供的信息,似乎可能是你的服务器不接受该端口上的连接引起的问题。我建议你查看一下该端口是否对你尝试连接的客户端开放,或者你的IMAP服务器是否接受TLS连接。

如果在进一步调试后你确定这不是服务器问题,我建议你在项目的GitHub问题跟踪器上提交一个问题,以获取那些更熟悉该包的人的帮助,毕竟它是一个第三方包。

英文:

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.

huangapple
  • 本文由 发表于 2015年8月3日 06:49:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/31777395.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定