2

我正在编写一个可以使用 LuaSocket SMTP 发送电子邮件的脚本。现在我想让我的脚本也能够阅读我的电子邮件。

我在支持 IMAP 的服务中有一个电子邮件帐户。

IMAP host and port: example.com:143
My E-Mail: doesnotexist@example.com
The password: notsaying

如何让我的脚本从该服务获取电子邮件以便显示其内容?

编辑:

我已经从https://github.com/vrld/imap4.lua尝试了 imap4,但似乎还没有完成。

我试过这个例子

require 'luarocks.require'

local imap4 = require 'imap4'

local username = "doesnotexist@example.com"
local password = "notsaying"

local connection = imap4('example.com', 143)

print(table.concat(connection:capability(), ', '))
assert(connection:isCapable('IMAP4rev1'))

connection:login(username, password)

for mb, info in pairs(connection:lsub()) do
    local stat = connection:status(mb, {'MESSAGES', 'RECENT', 'UNSEEN'})
    print(mb, stat.MESSAGES, stat.RECENT, stat.UNSEEN)
end

local info = connection:examine('INBOX')
print(info.exist, info.recent)

for _,v in pairs(connection:fetch('UID BODY.PEEK[HEADER.FIELDS (From Date Subject)]', (info.exist-3)..':*')) do
    print(v.id, v.UID, v.BODY.value)
end

connection:logout()

我只添加了用户名和密码,并从原始示例更改了服务器和端口,并将最新的从 4 更改为 3。我还删除了评论,因为它们很多。除了我没有修改任何其他内容之外,它基本上是相同的示例。

它似乎使用我的凭据以及正确的服务器和端口正确登录,但它有某种我无法调试的问题。

上面的示例输出:

IMAP4rev1, CHILDREN, NAMESPACE
INBOX.Sent  3   0   0
INBOX   4   0   0
4   0
lua: example.lua:24: attempt to index field 'BODY' (a nil value)
stack traceback:
    example.lua:24: in main chunk
    [C]: ?

它显示我的收件箱中有 4 封电子邮件,我的已发送电子邮件中有 3 封,这是正确的。

4

2 回答 2

1

这个例子使用 imap4 库来获取消息和 pop3.message 来解析。

local imap4   = require "imap4"
local Message = require "pop3.message"

local connection = imap4('imap.qip.ru', 143)

assert(connection:isCapable('IMAP4rev1'))

connection:login('****', '****')

-- Select INBOX with read only permissions.
local info = connection:examine('INBOX')
print(info.exist, info.recent)

-- List info on the 4 most recent mails.
for _,v in pairs(connection:fetch('RFC822', (info.exist-4)..':*')) do
    print("-------------------------")
    local msg = Message(v.RFC822)
    print("ID:         ", msg:id())
    print("subject:    ", msg:subject())
    print("to:         ", msg:to())
    print("from:       ", msg:from())
    print("from addr:  ", msg:from_address())
    print("reply:      ", msg:reply_to())
    print("reply addr: ", msg:reply_address())
    print("trunc:      ", msg:is_truncated())
    for i,v in ipairs(msg:full_content()) do
        if v.text then  print("  ", i , "TEXT: ", v.type, #v.text)
        else print("  ", i , "FILE: ", v.type, v.file_name or v.name, #v.data) end
    end
end

-- close connection
connection:logout()
于 2014-06-18T05:59:30.493 回答
0

首先尝试moeus的解决方案。如果您需要使用的服务器不支持 RFC822 或通常不符合标准,请仅使用我的示例。

在这个答案中,我将简要解释为什么原始示例不起作用,并给出一个没有 RFC822 的示例,因为我必须使用的服务器不理解 RFC822,以及根据IMAP 4它应该理解的许多其他关键字标准

在示例中,我必须更改:

connection:fetch('UID BODY.PEEK[HEADER.FIELDS (From Date Subject)]', (info.exist-3)..':*'))

至:

connection:fetch('(UID BODY.PEEK[HEADER.FIELDS (From Date Subject)])', (info.exist-3)..':*'))

注意括号,这就是示例不起作用的原因。

Moteus 对 RFC822 的回答对我不起作用,因为我必须使用的服务器是非标准的。这是我如何让它工作的:

local imap4   = require "imap4"
local Message = require "pop3.message"

local connection = imap4('imap.qip.ru', 143)

assert(connection:isCapable('IMAP4rev1'))

connection:login('****', '****')

-- Select INBOX with read only permissions.
local info = connection:examine('INBOX')
print(info.exist, info.recent)

-- List info on the 4 most recent mails.
for _,v in pairs(connection:fetch('(UID BODY.PEEK[HEADER.FIELDS (Subject To From Date)])', (info.exist-4)..':*')) do
    print("-------------------------")
    local msg = Message(v.BODY.value)
    print("ID:         ", msg:id())
    print("subject:    ", msg:subject())
    print("to:         ", msg:to())
    print("from:       ", msg:from())
    print("from addr:  ", msg:from_address())
    print("reply:      ", msg:reply_to())
    print("reply addr: ", msg:reply_address())
    print("trunc:      ", msg:is_truncated())
    for i,v in ipairs(msg:full_content()) do
        if v.text then  print("  ", i , "TEXT: ", v.type, #v.text)
        else print("  ", i , "FILE: ", v.type, v.file_name or v.name, #v.data) end
    end
end

-- close connection
connection:logout()

与 Moteus 的示例不同,您必须单独获取文本。

您可以像这样获取邮件的文本:

connection:fetch('(BODY.PEEK[TEXT])', id)
于 2014-06-18T12:45:43.100 回答