1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ POP3 (RFCs 1939, 2595) client.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
9 * Gunnar Ritter. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Gunnar Ritter
22 * and his contributors.
23 * 4. Neither the name of Gunnar Ritter nor the names of his contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 #ifndef HAVE_AMALGAMATION
49 #define POP3_ANSWER(RV,ACTIONSTOP) \
50 do if (((RV) = pop3_answer(mp)) == STOP) {\
54 #define POP3_OUT(RV,X,Y,ACTIONSTOP) \
56 if (((RV) = pop3_finish(mp)) == STOP) {\
59 if (options & OPT_VERBVERB)\
62 if (((RV) = swrite(&mp->mb_sock, X)) == STOP) {\
67 static char *_pop3_buf
;
68 static size_t _pop3_bufsize
;
69 static sigjmp_buf _pop3_jmp
;
70 static sighandler_type _pop3_savealrm
;
71 static int _pop3_keepalive
;
72 static int volatile _pop3_lock
;
74 /* Perform entire login handshake */
75 static enum okay
_pop3_login(struct mailbox
*mp
, struct sockconn
*scp
);
77 /* APOP: get greeting credential or NULL */
79 static char * _pop3_lookup_apop_timestamp(char const *bp
);
82 /* Several authentication methods */
84 static enum okay
_pop3_auth_apop(struct mailbox
*mp
,
85 struct sockconn
const *scp
, char const *ts
);
87 static enum okay
_pop3_auth_plain(struct mailbox
*mp
,
88 struct sockconn
const *scp
);
90 static void pop3_timer_off(void);
91 static enum okay
pop3_answer(struct mailbox
*mp
);
92 static enum okay
pop3_finish(struct mailbox
*mp
);
93 static void pop3catch(int s
);
94 static void _pop3_maincatch(int s
);
95 static enum okay
pop3_noop1(struct mailbox
*mp
);
96 static void pop3alarm(int s
);
97 static enum okay
pop3_stat(struct mailbox
*mp
, off_t
*size
, int *cnt
);
98 static enum okay
pop3_list(struct mailbox
*mp
, int n
, size_t *size
);
99 static void pop3_setptr(struct mailbox
*mp
,
100 struct sockconn
const *scp
);
101 static enum okay
pop3_get(struct mailbox
*mp
, struct message
*m
,
103 static enum okay
pop3_exit(struct mailbox
*mp
);
104 static enum okay
pop3_delete(struct mailbox
*mp
, int n
);
105 static enum okay
pop3_update(struct mailbox
*mp
);
108 _pop3_login(struct mailbox
*mp
, struct sockconn
*scp
)
113 enum okey_xlook_mode oxm
;
117 oxm
= ok_blook(v15_compat
) ? OXM_ALL
: OXM_PLAIN
| OXM_U_H_P
;
119 /* Get the greeting, check wether APOP is advertised */
120 POP3_ANSWER(rv
, goto jleave
);
122 ts
= _pop3_lookup_apop_timestamp(_pop3_buf
);
125 /* If not yet secured, can we upgrade to TLS? */
127 if (!scp
->sc_url
.url_needs_tls
&&
128 xok_blook(pop3_use_starttls
, &scp
->sc_url
, oxm
)) {
129 POP3_OUT(rv
, "STLS" NETNL
, MB_COMD
, goto jleave
);
130 POP3_ANSWER(rv
, goto jleave
);
131 if ((rv
= ssl_open(&scp
->sc_url
, &scp
->sc_sock
)) != OKAY
)
135 if (xok_blook(pop3_use_starttls
, &scp
->sc_url
, oxm
)) {
136 n_err(_("No SSL support compiled in\n"));
142 /* Use the APOP single roundtrip? */
144 if (ts
!= NULL
&& !xok_blook(pop3_no_apop
, &scp
->sc_url
, oxm
)) {
145 if ((rv
= _pop3_auth_apop(mp
, scp
, ts
)) != OKAY
) {
146 char const *ccp
= "";
148 if (scp
->sc_sock
.s_use_ssl
)
149 ccp
= _(" (over an encrypted connection)");
151 n_err(_("POP3 \"APOP\" authentication failed!\n"
152 " The server indicated support - but disable via *pop3-no-apop*\n"
153 " to use plain text authentication%s\n"), ccp
);
159 rv
= _pop3_auth_plain(mp
, scp
);
167 _pop3_lookup_apop_timestamp(char const *bp
)
170 * A POP3 server which implements the APOP command will include
171 * a timestamp in its banner greeting. The syntax of the timestamp
172 * corresponds to the "msg-id" in [RFC822]
174 * msg-id = "<" addr-spec ">"
175 * addr-spec = local-part "@" domain */
182 if ((cp
= strchr(bp
, '<')) == NULL
)
185 /* xxx What about malformed APOP timestamp (<@>) here? */
186 for (ep
= cp
; *ep
!= '\0'; ++ep
) {
191 else if (*ep
== '>') {
200 tl
= PTR2SIZE(++ep
- cp
);
212 _pop3_auth_apop(struct mailbox
*mp
, struct sockconn
const *scp
, char const *ts
)
214 unsigned char digest
[16];
215 char hex
[MD5TOHEX_SIZE
], *cp
;
222 md5_update(&ctx
, (uc_i
*)UNCONST(ts
), strlen(ts
));
223 md5_update(&ctx
, (uc_i
*)scp
->sc_cred
.cc_pass
.s
, scp
->sc_cred
.cc_pass
.l
);
224 md5_final(digest
, &ctx
);
225 md5tohex(hex
, digest
);
227 i
= scp
->sc_cred
.cc_user
.l
;
228 cp
= ac_alloc(5 + i
+ 1 + MD5TOHEX_SIZE
+ sizeof(NETNL
)-1 +1);
230 memcpy(cp
, "APOP ", 5);
231 memcpy(cp
+ 5, scp
->sc_cred
.cc_user
.s
, i
);
234 memcpy(cp
+ i
, hex
, MD5TOHEX_SIZE
);
236 memcpy(cp
+ i
, NETNL
, sizeof(NETNL
));
237 POP3_OUT(rv
, cp
, MB_COMD
, goto jleave
);
238 POP3_ANSWER(rv
, goto jleave
);
246 #endif /* HAVE_MD5 */
249 _pop3_auth_plain(struct mailbox
*mp
, struct sockconn
const *scp
)
255 /* The USER/PASS plain text version */
256 cp
= ac_alloc(MAX(scp
->sc_cred
.cc_user
.l
, scp
->sc_cred
.cc_pass
.l
) + 5 +
259 memcpy(cp
, "USER ", 5);
260 memcpy(cp
+ 5, scp
->sc_cred
.cc_user
.s
, scp
->sc_cred
.cc_user
.l
);
261 memcpy(cp
+ 5 + scp
->sc_cred
.cc_user
.l
, NETNL
, sizeof(NETNL
));
262 POP3_OUT(rv
, cp
, MB_COMD
, goto jleave
);
263 POP3_ANSWER(rv
, goto jleave
);
265 memcpy(cp
, "PASS ", 5);
266 memcpy(cp
+ 5, scp
->sc_cred
.cc_pass
.s
, scp
->sc_cred
.cc_pass
.l
);
267 memcpy(cp
+ 5 + scp
->sc_cred
.cc_pass
.l
, NETNL
, sizeof(NETNL
));
268 POP3_OUT(rv
, cp
, MB_COMD
, goto jleave
);
269 POP3_ANSWER(rv
, goto jleave
);
282 if (_pop3_keepalive
> 0) {
284 safe_signal(SIGALRM
, _pop3_savealrm
);
290 pop3_answer(struct mailbox
*mp
)
298 if ((sz
= sgetline(&_pop3_buf
, &_pop3_bufsize
, &blen
, &mp
->mb_sock
)) > 0) {
299 if ((mp
->mb_active
& (MB_COMD
| MB_MULT
)) == MB_MULT
)
301 if (options
& OPT_VERBVERB
)
303 switch (*_pop3_buf
) {
306 mp
->mb_active
&= ~MB_COMD
;
310 mp
->mb_active
= MB_NONE
;
312 (_pop3_buf
[blen
- 1] == NETNL
[0] ||
313 _pop3_buf
[blen
- 1] == NETNL
[1]))
314 _pop3_buf
[--blen
] = '\0';
315 n_err(_("POP3 error: %s\n"), _pop3_buf
);
318 /* If the answer starts neither with '+' nor with '-', it must be part
319 * of a multiline response. Get lines until a single dot appears */
321 while (_pop3_buf
[0] != '.' || _pop3_buf
[1] != NETNL
[0] ||
322 _pop3_buf
[2] != NETNL
[1] || _pop3_buf
[3] != '\0') {
323 sz
= sgetline(&_pop3_buf
, &_pop3_bufsize
, NULL
, &mp
->mb_sock
);
327 mp
->mb_active
&= ~MB_MULT
;
328 if (mp
->mb_active
!= MB_NONE
)
334 mp
->mb_active
= MB_NONE
;
341 pop3_finish(struct mailbox
*mp
)
344 while (mp
->mb_sock
.s_fd
> 0 && mp
->mb_active
!= MB_NONE
)
353 NYD_X
; /* Signal handler */
356 /*n_err_sighdl(_("Interrupt during POP3 operation\n"));*/
357 interrupts
= 2; /* Force "Interrupt" message shall we onintr(0) */
358 siglongjmp(_pop3_jmp
, 1);
361 n_err_sighdl(_("Received SIGPIPE during POP3 operation\n"));
367 _pop3_maincatch(int s
)
369 NYD_X
; /* Signal handler */
371 if (interrupts
++ == 0)
372 n_err_sighdl(_("\n(Interrupt -- one more to abort operation)\n"));
374 siglongjmp(_pop3_jmp
, 1);
378 pop3_noop1(struct mailbox
*mp
)
383 POP3_OUT(rv
, "NOOP" NETNL
, MB_COMD
, goto jleave
);
384 POP3_ANSWER(rv
, goto jleave
);
393 sighandler_type
volatile saveint
, savepipe
;
394 NYD_X
; /* Signal handler */
397 if (_pop3_lock
++ == 0) {
399 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
400 safe_signal(SIGINT
, &_pop3_maincatch
);
401 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
402 if (sigsetjmp(_pop3_jmp
, 1)) {
404 safe_signal(SIGINT
, saveint
);
405 safe_signal(SIGPIPE
, savepipe
);
408 if (savepipe
!= SIG_IGN
)
409 safe_signal(SIGPIPE
, pop3catch
);
411 if (pop3_noop1(&mb
) != OKAY
) {
412 safe_signal(SIGINT
, saveint
);
413 safe_signal(SIGPIPE
, savepipe
);
416 safe_signal(SIGINT
, saveint
);
417 safe_signal(SIGPIPE
, savepipe
);
420 alarm(_pop3_keepalive
);
426 pop3_stat(struct mailbox
*mp
, off_t
*size
, int *cnt
)
432 POP3_OUT(rv
, "STAT" NETNL
, MB_COMD
, goto jleave
);
433 POP3_ANSWER(rv
, goto jleave
);
435 for (cp
= _pop3_buf
; *cp
!= '\0' && !spacechar(*cp
); ++cp
)
437 while (*cp
!= '\0' && spacechar(*cp
))
441 *cnt
= (int)strtol(cp
, NULL
, 10);
442 while (*cp
!= '\0' && !spacechar(*cp
))
444 while (*cp
!= '\0' && spacechar(*cp
))
447 *size
= (int)strtol(cp
, NULL
, 10);
454 n_err(_("Invalid POP3 STAT response: %s\n"), _pop3_buf
);
461 pop3_list(struct mailbox
*mp
, int n
, size_t *size
)
463 char o
[LINESIZE
], *cp
;
467 snprintf(o
, sizeof o
, "LIST %u" NETNL
, n
);
468 POP3_OUT(rv
, o
, MB_COMD
, goto jleave
);
469 POP3_ANSWER(rv
, goto jleave
);
471 for (cp
= _pop3_buf
; *cp
!= '\0' && !spacechar(*cp
); ++cp
)
473 while (*cp
!= '\0' && spacechar(*cp
))
475 while (*cp
!= '\0' && !spacechar(*cp
))
477 while (*cp
!= '\0' && spacechar(*cp
))
480 *size
= (size_t)strtol(cp
, NULL
, 10);
487 pop3_setptr(struct mailbox
*mp
, struct sockconn
const *scp
)
493 message
= scalloc(msgCount
+ 1, sizeof *message
);
494 message
[msgCount
].m_size
= 0;
495 message
[msgCount
].m_lines
= 0;
496 dot
= message
; /* (Just do it: avoid crash -- shall i now do ointr(0).. */
498 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
) {
499 struct message
*m
= message
+ i
;
500 m
->m_flag
= MUSED
| MNEW
| MNOFROM
| MNEWEST
;
503 m
->m_size
= m
->m_xsize
= 0;
506 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
)
507 if (!pop3_list(mp
, i
+ 1, &message
[i
].m_xsize
))
510 /* Force the load of all messages right now */
511 ns
= xok_blook(pop3_bulk_load
, &scp
->sc_url
, OXM_ALL
)
512 ? NEED_BODY
: NEED_HEADER
;
513 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
)
514 if (!pop3_get(mp
, message
+ i
, ns
))
518 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
) {
519 struct message
*m
= message
+ i
;
522 if ((cp
= hfield1("status", m
)) != NULL
)
523 while (*cp
!= '\0') {
542 pop3_get(struct mailbox
*mp
, struct message
*m
, enum needspec
volatile need
)
544 char o
[LINESIZE
], *line
, *lp
;
545 sighandler_type
volatile saveint
, savepipe
;
546 size_t linesize
, linelen
, size
;
548 int volatile emptyline
;
550 enum okay
volatile rv
;
553 line
= NULL
; /* TODO line pool */
554 saveint
= savepipe
= SIG_IGN
;
556 number
= (int)PTR2SIZE(m
- message
+ 1);
560 if (mp
->mb_sock
.s_fd
< 0) {
561 n_err(_("POP3 connection already closed\n"));
566 if (_pop3_lock
++ == 0) {
568 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
569 safe_signal(SIGINT
, &_pop3_maincatch
);
570 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
571 if (sigsetjmp(_pop3_jmp
, 1))
573 if (savepipe
!= SIG_IGN
)
574 safe_signal(SIGPIPE
, pop3catch
);
578 fseek(mp
->mb_otf
, 0L, SEEK_END
);
579 offset
= ftell(mp
->mb_otf
);
583 snprintf(o
, sizeof o
, "TOP %u 0" NETNL
, number
);
586 snprintf(o
, sizeof o
, "RETR %u" NETNL
, number
);
591 POP3_OUT(rv
, o
, MB_COMD
| MB_MULT
, goto jleave
);
593 if (pop3_answer(mp
) == STOP
) {
594 if (need
== NEED_HEADER
) {
595 /* The TOP POP3 command is optional, so retry with entire message */
604 while (sgetline(&line
, &linesize
, &linelen
, &mp
->mb_sock
) > 0) {
605 if (line
[0] == '.' && line
[1] == NETNL
[0] && line
[2] == NETNL
[1] &&
607 mp
->mb_active
&= ~MB_MULT
;
610 if (line
[0] == '.') {
616 * Need to mask 'From ' lines. This cannot be done properly
617 * since some servers pass them as 'From ' and others as
618 * '>From '. Although one could identify the first kind of
619 * server in principle, it is not possible to identify the
620 * second as '>From ' may also come from a server of the
621 * first type as actual data. So do what is absolutely
622 * necessary only - mask 'From '.
624 * If the line is the first line of the message header, it
625 * is likely a real 'From ' line. In this case, it is just
626 * ignored since it violates all standards.
627 * TODO i have *never* seen the latter?!?!?
630 /* Since we simply copy over data without doing any transfer
631 * encoding reclassification/adjustment we *have* to perform
632 * RFC 4155 compliant From_ quoting here */
633 if (emptyline
&& is_head(lp
, linelen
, TRU1
)) {
634 putc('>', mp
->mb_otf
);
638 if (lp
[linelen
-1] == NETNL
[1] &&
639 (linelen
== 1 || lp
[linelen
-2] == NETNL
[0])) {
640 emptyline
= linelen
<= 2;
642 fwrite(lp
, 1, linelen
- 2, mp
->mb_otf
);
643 putc('\n', mp
->mb_otf
);
647 fwrite(lp
, 1, linelen
, mp
->mb_otf
);
652 /* This is very ugly; but some POP3 daemons don't end a
653 * message with NETNL NETNL, and we need \n\n for mbox format */
654 putc('\n', mp
->mb_otf
);
660 m
->m_block
= mailx_blockof(offset
);
661 m
->m_offset
= mailx_offsetof(offset
);
666 m
->m_have
|= HAVE_HEADER
;
669 m
->m_have
|= HAVE_HEADER
| HAVE_BODY
;
670 m
->m_xlines
= m
->m_lines
;
671 m
->m_xsize
= m
->m_size
;
681 if (saveint
!= SIG_IGN
)
682 safe_signal(SIGINT
, saveint
);
683 if (savepipe
!= SIG_IGN
)
684 safe_signal(SIGPIPE
, savepipe
);
693 pop3_exit(struct mailbox
*mp
)
698 POP3_OUT(rv
, "QUIT" NETNL
, MB_COMD
, goto jleave
);
699 POP3_ANSWER(rv
, goto jleave
);
706 pop3_delete(struct mailbox
*mp
, int n
)
712 snprintf(o
, sizeof o
, "DELE %u" NETNL
, n
);
713 POP3_OUT(rv
, o
, MB_COMD
, goto jleave
);
714 POP3_ANSWER(rv
, goto jleave
);
721 pop3_update(struct mailbox
*mp
)
724 int dodel
, c
, gotcha
, held
;
727 if (!(pstate
& PS_EDIT
)) {
730 for (m
= message
; PTRCMP(m
, <, message
+ msgCount
); ++m
)
731 if (m
->m_flag
& MBOX
)
738 for (m
= message
; PTRCMP(m
, <, message
+ msgCount
); ++m
) {
739 if (pstate
& PS_EDIT
)
740 dodel
= m
->m_flag
& MDELETED
;
742 dodel
= !((m
->m_flag
& MPRESERVE
) || !(m
->m_flag
& MTOUCH
));
744 pop3_delete(mp
, PTR2SIZE(m
- message
+ 1));
749 if (gotcha
&& (pstate
& PS_EDIT
)) {
750 printf(_("\"%s\" "), displayname
);
751 printf((ok_blook(bsdcompat
) || ok_blook(bsdmsgs
))
752 ? _("complete\n") : _("updated\n"));
753 } else if (held
&& !(pstate
& PS_EDIT
)) {
755 printf(_("Held 1 message in %s\n"), displayname
);
757 printf(_("Held %d messages in %s\n"), held
, displayname
);
767 sighandler_type
volatile saveint
, savepipe
;
773 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
774 safe_signal(SIGINT
, &_pop3_maincatch
);
775 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
776 if (sigsetjmp(_pop3_jmp
, 1) == 0) {
777 if (savepipe
!= SIG_IGN
)
778 safe_signal(SIGPIPE
, pop3catch
);
780 rv
= pop3_noop1(&mb
);
782 safe_signal(SIGINT
, saveint
);
783 safe_signal(SIGPIPE
, savepipe
);
790 pop3_setfile(char const *server
, enum fedit_mode fm
)
793 sighandler_type saveint
, savepipe
;
799 if (fm
& FEDIT_NEWMAIL
)
803 if (!url_parse(&sc
.sc_url
, CPROTO_POP3
, server
))
805 if (!ok_blook(v15_compat
) &&
806 (!sc
.sc_url
.url_had_user
|| sc
.sc_url
.url_pass
.s
!= NULL
)) {
807 n_err(_("New-style URL used without *v15-compat* being set\n"));
811 if (!(ok_blook(v15_compat
) ? ccred_lookup(&sc
.sc_cred
, &sc
.sc_url
)
812 : ccred_lookup_old(&sc
.sc_cred
, CPROTO_POP3
,
813 (sc
.sc_url
.url_had_user
? sc
.sc_url
.url_eu_h_p
.s
814 : sc
.sc_url
.url_u_h_p
.s
))))
820 if (!sopen(&sc
.sc_sock
, &sc
.sc_url
))
825 if (fm
& FEDIT_SYSBOX
)
829 if (mb
.mb_sock
.s_fd
>= 0)
840 initbox(sc
.sc_url
.url_p_u_h_p
);
841 mb
.mb_type
= MB_VOID
;
843 mb
.mb_sock
= sc
.sc_sock
;
845 saveint
= safe_signal(SIGINT
, SIG_IGN
);
846 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
847 if (sigsetjmp(_pop3_jmp
, 1)) {
849 n_err(_("POP3 connection closed\n"));
850 safe_signal(SIGINT
, saveint
);
851 safe_signal(SIGPIPE
, savepipe
);
858 if (saveint
!= SIG_IGN
)
859 safe_signal(SIGINT
, pop3catch
);
860 if (savepipe
!= SIG_IGN
)
861 safe_signal(SIGPIPE
, pop3catch
);
863 if ((cp
= xok_vlook(pop3_keepalive
, &sc
.sc_url
, OXM_ALL
)) != NULL
) {
864 if ((_pop3_keepalive
= (int)strtol(cp
, NULL
, 10)) > 0) {
865 _pop3_savealrm
= safe_signal(SIGALRM
, pop3alarm
);
866 alarm(_pop3_keepalive
);
870 mb
.mb_sock
.s_desc
= sc
.sc_url
.url_needs_tls
? "POP3S" : "POP3";
871 mb
.mb_sock
.s_onclose
= pop3_timer_off
;
872 if (_pop3_login(&mb
, &sc
) != OKAY
||
873 pop3_stat(&mb
, &mailsize
, &msgCount
) != OKAY
) {
876 safe_signal(SIGINT
, saveint
);
877 safe_signal(SIGPIPE
, savepipe
);
883 mb
.mb_type
= MB_POP3
;
884 mb
.mb_perm
= ((options
& OPT_R_FLAG
) || (fm
& FEDIT_RDONLY
)) ? 0 : MB_DELE
;
885 pop3_setptr(&mb
, &sc
);
887 /*if (!(fm & FEDIT_NEWMAIL)) */{
888 pstate
&= ~PS_SAW_COMMAND
;
889 pstate
|= PS_SETFILE_OPENED
;
892 safe_signal(SIGINT
, saveint
);
893 safe_signal(SIGPIPE
, savepipe
);
896 if ((options
& OPT_EXISTONLY
) && !(options
& OPT_HEADERLIST
)) {
897 rv
= (msgCount
== 0);
901 if (!(pstate
& PS_EDIT
) && msgCount
== 0) {
902 if (!ok_blook(emptystart
))
903 n_err(_("No mail at %s\n"), server
);
914 pop3_header(struct message
*m
)
919 /* TODO no URL here, no OXM possible; (however it is used in setfile()..) */
920 rv
= pop3_get(&mb
, m
, (ok_blook(pop3_bulk_load
) ? NEED_BODY
: NEED_HEADER
));
926 pop3_body(struct message
*m
)
931 rv
= pop3_get(&mb
, m
, NEED_BODY
);
939 sighandler_type
volatile saveint
, savepipe
;
945 if (mb
.mb_sock
.s_fd
< 0) {
946 n_err(_("POP3 connection already closed\n"));
952 saveint
= safe_signal(SIGINT
, SIG_IGN
);
953 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
954 if (sigsetjmp(_pop3_jmp
, 1)) {
955 safe_signal(SIGINT
, saveint
);
956 safe_signal(SIGPIPE
, savepipe
);
961 if (saveint
!= SIG_IGN
)
962 safe_signal(SIGINT
, pop3catch
);
963 if (savepipe
!= SIG_IGN
)
964 safe_signal(SIGPIPE
, pop3catch
);
968 safe_signal(SIGINT
, saveint
);
969 safe_signal(SIGPIPE
, savepipe
);
977 #endif /* HAVE_POP3 */