I want to fetch and delete the top message (with UID=1) through IMAP using curl. I can do it in multiple commands, however when I send the delete command, I have no guarantee that the uid has not changed. Is there a way to persist the imap (or pop3) session in curl?
You actually do have a guarantee that the UID has not changed: this is what the IMAP UIDVALIDITY
field is all about. As long as the UIDVALIDITY
value for a mailbox has not changed, any message UIDs you have will continue to point to the same message. Read about this in more detail in the IMAP RFC.
Using curl, you can assert a UIDVALIDITY
value in a request by including that in the IMAP URL, like this:
curl 'imaps://imap.example.com/inbox;UIDVALIDITY=6' ...
If the UIDVALIDITY
has changed, curl
will report:
curl: (78) Mailbox UIDVALIDITY has changed
You can see the UIDVALIDITY
value for a mailbox by passing the -v
option to curl
when doing, e.g., an EXAMINE
:
$ curl -v imaps://imap.example.com/ -X 'examine inbox'
[...]
> A003 examine inbox
< * FLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing Old SEEN)
< * OK [PERMANENTFLAGS ()] Flags permitted.
< * OK [UIDVALIDITY 7] UIDs valid.
< * 9 EXISTS
< * 0 RECENT
< * OK [UIDNEXT 7422] Predicted next UID.
< * OK [HIGHESTMODSEQ 14264365]
< A003 OK [READ-ONLY] inbox selected. (Success)
A necessary prerequisite to using the UIDVALIDITY
value is to request message uids. You can ask for the UID
attribute when fetching information about messages:
$ curl -sv --netrc 'imaps://imap.example.com/inbox' -X 'fetch 1:* (UID FLAGS)'
[...]
< * 1 FETCH (UID 7186 FLAGS (\Seen))
< * 2 FETCH (UID 7188 FLAGS (\Seen))
< * 3 FETCH (UID 7278 FLAGS (\Seen))
< * 4 FETCH (UID 7288 FLAGS (Old \Seen))
< * 5 FETCH (UID 7364 FLAGS (\Seen))
< * 6 FETCH (UID 7413 FLAGS (\Seen))
< * 7 FETCH (UID 7417 FLAGS (\Seen))
< * 8 FETCH (UID 7419 FLAGS (\Seen))
< * 9 FETCH (UID 7421 FLAGS (\Seen))
Once you have a UID
, you can use that to refer to a message by prefixing commands with the UID
keyword. For example, instead of asking for message 9 like this:
FETCH 9 (ENVELOPE)
We would instead need to send the following IMAP command:
UID FETCH 7421 (ENVELOPE)
Curl doesn't appear to have native support for UID
commands, but we can pass custom commands using the -X
option. For example, to fetch message with UID 7421, we would run:
curl 'imaps://imap.example.com/inbox;uidvalidity=7' -X 'UID FETCH 7421 (ENVELOPE)'
This would assert that the mailbox UIDVALIDITY
must still be 7
(because if it has changed, our UID is no longer valid), and retrieve the message envelope.
To delete that message:
curl 'imaps://imap.example.com/inbox;uidvalidity=7' -X 'UID STORE 7421 +Flags \Deleted'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With