1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ POP3 (RFCs 1939, 2595) client.
3 *@ TODO UIDL (as struct message.m_uid, *headline* %U), etc...
5 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
6 * Copyright (c) 2012 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
7 * SPDX-License-Identifier: BSD-4-Clause
11 * Gunnar Ritter. All rights reserved.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by Gunnar Ritter
24 * and his contributors.
25 * 4. Neither the name of Gunnar Ritter nor the names of his contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 #ifndef HAVE_AMALGAMATION
51 #define POP3_ANSWER(RV,ACTIONSTOP) \
52 do if (((RV) = pop3_answer(mp)) == STOP) {\
56 #define POP3_OUT(RV,X,Y,ACTIONSTOP) \
58 if (((RV) = pop3_finish(mp)) == STOP) {\
61 if (n_poption & n_PO_VERBVERB)\
64 if (((RV) = swrite(&mp->mb_sock, X)) == STOP) {\
69 static char *_pop3_buf
;
70 static size_t _pop3_bufsize
;
71 static sigjmp_buf _pop3_jmp
;
72 static sighandler_type _pop3_savealrm
;
73 static si32_t _pop3_keepalive
;
74 static int volatile _pop3_lock
;
76 /* Perform entire login handshake */
77 static enum okay
_pop3_login(struct mailbox
*mp
, struct sockconn
*scp
);
79 /* APOP: get greeting credential or NULL */
81 static char * _pop3_lookup_apop_timestamp(char const *bp
);
84 /* Several authentication methods */
86 static enum okay
_pop3_auth_apop(struct mailbox
*mp
,
87 struct sockconn
const *scp
, char const *ts
);
89 static enum okay
_pop3_auth_plain(struct mailbox
*mp
,
90 struct sockconn
const *scp
);
92 static void pop3_timer_off(void);
93 static enum okay
pop3_answer(struct mailbox
*mp
);
94 static enum okay
pop3_finish(struct mailbox
*mp
);
95 static void pop3catch(int s
);
96 static void _pop3_maincatch(int s
);
97 static enum okay
pop3_noop1(struct mailbox
*mp
);
98 static void pop3alarm(int s
);
99 static enum okay
pop3_stat(struct mailbox
*mp
, off_t
*size
, int *cnt
);
100 static enum okay
pop3_list(struct mailbox
*mp
, int n
, size_t *size
);
101 static void pop3_setptr(struct mailbox
*mp
,
102 struct sockconn
const *scp
);
103 static enum okay
pop3_get(struct mailbox
*mp
, struct message
*m
,
105 static enum okay
pop3_exit(struct mailbox
*mp
);
106 static enum okay
pop3_delete(struct mailbox
*mp
, int n
);
107 static enum okay
pop3_update(struct mailbox
*mp
);
110 _pop3_login(struct mailbox
*mp
, struct sockconn
*scp
)
115 enum okey_xlook_mode oxm
;
119 oxm
= ok_blook(v15_compat
) ? OXM_ALL
: OXM_PLAIN
| OXM_U_H_P
;
121 /* Get the greeting, check whether APOP is advertised */
122 POP3_ANSWER(rv
, goto jleave
);
124 ts
= _pop3_lookup_apop_timestamp(_pop3_buf
);
127 /* If not yet secured, can we upgrade to TLS? */
129 if (!(scp
->sc_url
.url_flags
& n_URL_TLS_REQUIRED
) &&
130 xok_blook(pop3_use_starttls
, &scp
->sc_url
, oxm
)) {
131 POP3_OUT(rv
, "STLS" NETNL
, MB_COMD
, goto jleave
);
132 POP3_ANSWER(rv
, goto jleave
);
133 if(!n_tls_open(&scp
->sc_url
, &scp
->sc_sock
)){
139 if (xok_blook(pop3_use_starttls
, &scp
->sc_url
, oxm
)) {
140 n_err(_("No TLS support compiled in\n"));
146 /* Use the APOP single roundtrip? */
148 if (ts
!= NULL
&& !xok_blook(pop3_no_apop
, &scp
->sc_url
, oxm
)) {
149 if ((rv
= _pop3_auth_apop(mp
, scp
, ts
)) != OKAY
) {
153 if (scp
->sc_sock
.s_use_tls
)
154 ccp
= _("over an encrypted connection");
157 ccp
= _("(unsafe clear text!)");
158 n_err(_("POP3 APOP authentication failed!\n"
159 " Server indicated support.. Set *pop3-no-apop*\n"
160 " for plain text authentication %s\n"), ccp
);
166 rv
= _pop3_auth_plain(mp
, scp
);
174 _pop3_lookup_apop_timestamp(char const *bp
)
177 * A POP3 server which implements the APOP command will include
178 * a timestamp in its banner greeting. The syntax of the timestamp
179 * corresponds to the "msg-id" in [RFC822]
181 * msg-id = "<" addr-spec ">"
182 * addr-spec = local-part "@" domain */
189 if ((cp
= strchr(bp
, '<')) == NULL
)
192 /* xxx What about malformed APOP timestamp (<@>) here? */
193 for (ep
= cp
; *ep
!= '\0'; ++ep
) {
198 else if (*ep
== '>') {
207 tl
= PTR2SIZE(++ep
- cp
);
208 rp
= n_autorec_alloc(tl
+1);
219 _pop3_auth_apop(struct mailbox
*mp
, struct sockconn
const *scp
, char const *ts
)
221 unsigned char digest
[16];
222 char hex
[MD5TOHEX_SIZE
], *cp
;
229 md5_update(&ctx
, (uc_i
*)n_UNCONST(ts
), strlen(ts
));
230 md5_update(&ctx
, (uc_i
*)scp
->sc_cred
.cc_pass
.s
, scp
->sc_cred
.cc_pass
.l
);
231 md5_final(digest
, &ctx
);
232 md5tohex(hex
, digest
);
234 i
= scp
->sc_cred
.cc_user
.l
;
235 cp
= n_lofi_alloc(5 + i
+ 1 + MD5TOHEX_SIZE
+ sizeof(NETNL
)-1 +1);
237 memcpy(cp
, "APOP ", 5);
238 memcpy(cp
+ 5, scp
->sc_cred
.cc_user
.s
, i
);
241 memcpy(cp
+ i
, hex
, MD5TOHEX_SIZE
);
243 memcpy(cp
+ i
, NETNL
, sizeof(NETNL
));
244 POP3_OUT(rv
, cp
, MB_COMD
, goto jleave
);
245 POP3_ANSWER(rv
, goto jleave
);
253 #endif /* HAVE_MD5 */
256 _pop3_auth_plain(struct mailbox
*mp
, struct sockconn
const *scp
)
262 /* The USER/PASS plain text version */
263 cp
= n_lofi_alloc(n_MAX(scp
->sc_cred
.cc_user
.l
, scp
->sc_cred
.cc_pass
.l
) +
264 5 + sizeof(NETNL
)-1 +1);
266 memcpy(cp
, "USER ", 5);
267 memcpy(cp
+ 5, scp
->sc_cred
.cc_user
.s
, scp
->sc_cred
.cc_user
.l
);
268 memcpy(cp
+ 5 + scp
->sc_cred
.cc_user
.l
, NETNL
, sizeof(NETNL
));
269 POP3_OUT(rv
, cp
, MB_COMD
, goto jleave
);
270 POP3_ANSWER(rv
, goto jleave
);
272 memcpy(cp
, "PASS ", 5);
273 memcpy(cp
+ 5, scp
->sc_cred
.cc_pass
.s
, scp
->sc_cred
.cc_pass
.l
);
274 memcpy(cp
+ 5 + scp
->sc_cred
.cc_pass
.l
, NETNL
, sizeof(NETNL
));
275 POP3_OUT(rv
, cp
, MB_COMD
, goto jleave
);
276 POP3_ANSWER(rv
, goto jleave
);
289 if (_pop3_keepalive
> 0) {
291 safe_signal(SIGALRM
, _pop3_savealrm
);
297 pop3_answer(struct mailbox
*mp
)
305 if ((sz
= sgetline(&_pop3_buf
, &_pop3_bufsize
, &blen
, &mp
->mb_sock
)) > 0) {
306 if ((mp
->mb_active
& (MB_COMD
| MB_MULT
)) == MB_MULT
)
308 if (n_poption
& n_PO_VERBVERB
)
310 switch (*_pop3_buf
) {
313 mp
->mb_active
&= ~MB_COMD
;
317 mp
->mb_active
= MB_NONE
;
319 (_pop3_buf
[blen
- 1] == NETNL
[0] ||
320 _pop3_buf
[blen
- 1] == NETNL
[1]))
321 _pop3_buf
[--blen
] = '\0';
322 n_err(_("POP3 error: %s\n"), _pop3_buf
);
325 /* If the answer starts neither with '+' nor with '-', it must be part
326 * of a multiline response. Get lines until a single dot appears */
328 while (_pop3_buf
[0] != '.' || _pop3_buf
[1] != NETNL
[0] ||
329 _pop3_buf
[2] != NETNL
[1] || _pop3_buf
[3] != '\0') {
330 sz
= sgetline(&_pop3_buf
, &_pop3_bufsize
, NULL
, &mp
->mb_sock
);
334 mp
->mb_active
&= ~MB_MULT
;
335 if (mp
->mb_active
!= MB_NONE
)
341 mp
->mb_active
= MB_NONE
;
348 pop3_finish(struct mailbox
*mp
)
351 while (mp
->mb_sock
.s_fd
> 0 && mp
->mb_active
!= MB_NONE
)
360 NYD_X
; /* Signal handler */
363 /*n_err_sighdl(_("Interrupt during POP3 operation\n"));*/
364 interrupts
= 2; /* Force "Interrupt" message shall we onintr(0) */
365 siglongjmp(_pop3_jmp
, 1);
367 n_err_sighdl(_("Received SIGPIPE during POP3 operation\n"));
373 _pop3_maincatch(int s
)
375 NYD_X
; /* Signal handler */
378 n_err_sighdl(_("\n(Interrupt -- one more to abort operation)\n"));
381 siglongjmp(_pop3_jmp
, 1);
386 pop3_noop1(struct mailbox
*mp
)
391 POP3_OUT(rv
, "NOOP" NETNL
, MB_COMD
, goto jleave
);
392 POP3_ANSWER(rv
, goto jleave
);
401 sighandler_type
volatile saveint
, savepipe
;
402 NYD_X
; /* Signal handler */
405 if (_pop3_lock
++ == 0) {
407 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
408 safe_signal(SIGINT
, &_pop3_maincatch
);
409 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
410 if (sigsetjmp(_pop3_jmp
, 1)) {
412 safe_signal(SIGINT
, saveint
);
413 safe_signal(SIGPIPE
, savepipe
);
416 if (savepipe
!= SIG_IGN
)
417 safe_signal(SIGPIPE
, pop3catch
);
419 if (pop3_noop1(&mb
) != OKAY
) {
420 safe_signal(SIGINT
, saveint
);
421 safe_signal(SIGPIPE
, savepipe
);
424 safe_signal(SIGINT
, saveint
);
425 safe_signal(SIGPIPE
, savepipe
);
428 alarm(_pop3_keepalive
);
434 pop3_stat(struct mailbox
*mp
, off_t
*size
, int *cnt
)
440 POP3_OUT(rv
, "STAT" NETNL
, MB_COMD
, goto jleave
);
441 POP3_ANSWER(rv
, goto jleave
);
443 for (cp
= _pop3_buf
; *cp
!= '\0' && !spacechar(*cp
); ++cp
)
445 while (*cp
!= '\0' && spacechar(*cp
))
452 if(n_idec_uiz_cp(&i
, cp
, 10, &cp
) & n_IDEC_STATE_EMASK
)
458 while(*cp
!= '\0' && !spacechar(*cp
))
460 while(*cp
!= '\0' && spacechar(*cp
))
465 if(n_idec_uiz_cp(&i
, cp
, 10, NULL
) & n_IDEC_STATE_EMASK
)
473 n_err(_("Invalid POP3 STAT response: %s\n"), _pop3_buf
);
480 pop3_list(struct mailbox
*mp
, int n
, size_t *size
)
482 char o
[LINESIZE
], *cp
;
486 snprintf(o
, sizeof o
, "LIST %u" NETNL
, n
);
487 POP3_OUT(rv
, o
, MB_COMD
, goto jleave
);
488 POP3_ANSWER(rv
, goto jleave
);
490 for (cp
= _pop3_buf
; *cp
!= '\0' && !spacechar(*cp
); ++cp
)
492 while (*cp
!= '\0' && spacechar(*cp
))
494 while (*cp
!= '\0' && !spacechar(*cp
))
496 while (*cp
!= '\0' && spacechar(*cp
))
499 n_idec_uiz_cp(size
, cp
, 10, NULL
);
506 pop3_setptr(struct mailbox
*mp
, struct sockconn
const *scp
)
512 message
= n_calloc(msgCount
+ 1, sizeof *message
);
513 message
[msgCount
].m_size
= 0;
514 message
[msgCount
].m_lines
= 0;
515 dot
= message
; /* (Just do it: avoid crash -- shall i now do ointr(0).. */
517 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
) {
518 struct message
*m
= message
+ i
;
519 m
->m_flag
= MUSED
| MNEW
| MNOFROM
| MNEWEST
;
522 m
->m_size
= m
->m_xsize
= 0;
525 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
)
526 if (!pop3_list(mp
, i
+ 1, &message
[i
].m_xsize
))
529 /* Force the load of all messages right now */
530 ns
= xok_blook(pop3_bulk_load
, &scp
->sc_url
, OXM_ALL
)
531 ? NEED_BODY
: NEED_HEADER
;
532 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
)
533 if (!pop3_get(mp
, message
+ i
, ns
))
537 for (i
= 0; UICMP(z
, i
, <, msgCount
); ++i
) {
538 struct message
*m
= message
+ i
;
541 if ((cp
= hfield1("status", m
)) != NULL
)
542 while (*cp
!= '\0') {
561 pop3_get(struct mailbox
*mp
, struct message
*m
, enum needspec
volatile need
)
563 char o
[LINESIZE
], *line
, *lp
;
564 sighandler_type
volatile saveint
, savepipe
;
565 size_t linesize
, linelen
, size
;
567 int volatile emptyline
;
569 enum okay
volatile rv
;
572 line
= NULL
; /* TODO line pool */
573 saveint
= savepipe
= SIG_IGN
;
575 number
= (int)PTR2SIZE(m
- message
+ 1);
579 if (mp
->mb_sock
.s_fd
< 0) {
580 n_err(_("POP3 connection already closed\n"));
585 if (_pop3_lock
++ == 0) {
587 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
588 safe_signal(SIGINT
, &_pop3_maincatch
);
589 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
590 if (sigsetjmp(_pop3_jmp
, 1))
592 if (savepipe
!= SIG_IGN
)
593 safe_signal(SIGPIPE
, pop3catch
);
597 fseek(mp
->mb_otf
, 0L, SEEK_END
);
598 offset
= ftell(mp
->mb_otf
);
602 snprintf(o
, sizeof o
, "TOP %u 0" NETNL
, number
);
605 snprintf(o
, sizeof o
, "RETR %u" NETNL
, number
);
610 POP3_OUT(rv
, o
, MB_COMD
| MB_MULT
, goto jleave
);
612 if (pop3_answer(mp
) == STOP
) {
613 if (need
== NEED_HEADER
) {
614 /* The TOP POP3 command is optional, so retry with entire message */
623 while (sgetline(&line
, &linesize
, &linelen
, &mp
->mb_sock
) > 0) {
624 if (line
[0] == '.' && line
[1] == NETNL
[0] && line
[2] == NETNL
[1] &&
626 mp
->mb_active
&= ~MB_MULT
;
629 if (line
[0] == '.') {
635 * Need to mask 'From ' lines. This cannot be done properly
636 * since some servers pass them as 'From ' and others as
637 * '>From '. Although one could identify the first kind of
638 * server in principle, it is not possible to identify the
639 * second as '>From ' may also come from a server of the
640 * first type as actual data. So do what is absolutely
641 * necessary only - mask 'From '.
643 * If the line is the first line of the message header, it
644 * is likely a real 'From ' line. In this case, it is just
645 * ignored since it violates all standards.
646 * TODO i have *never* seen the latter?!?!?
649 /* Since we simply copy over data without doing any transfer
650 * encoding reclassification/adjustment we *have* to perform
651 * RFC 4155 compliant From_ quoting here */
652 if (emptyline
&& is_head(lp
, linelen
, FAL0
)) {
653 putc('>', mp
->mb_otf
);
657 if (lp
[linelen
-1] == NETNL
[1] &&
658 (linelen
== 1 || lp
[linelen
-2] == NETNL
[0])) {
659 emptyline
= linelen
<= 2;
661 fwrite(lp
, 1, linelen
- 2, mp
->mb_otf
);
662 putc('\n', mp
->mb_otf
);
666 fwrite(lp
, 1, linelen
, mp
->mb_otf
);
671 /* TODO This is very ugly; but some POP3 daemons don't end a
672 * TODO message with NETNL NETNL, and we need \n\n for mbox format.
673 * TODO That is to say we do it wrong here in order to get it right
674 * TODO when send.c stuff or with MBOX handling, even though THIS
675 * TODO line is solely a property of the MBOX database format! */
676 putc('\n', mp
->mb_otf
);
682 m
->m_block
= mailx_blockof(offset
);
683 m
->m_offset
= mailx_offsetof(offset
);
688 m
->m_content_info
|= CI_HAVE_HEADER
;
691 m
->m_content_info
|= CI_HAVE_HEADER
| CI_HAVE_BODY
;
692 m
->m_xlines
= m
->m_lines
;
693 m
->m_xsize
= m
->m_size
;
703 if (saveint
!= SIG_IGN
)
704 safe_signal(SIGINT
, saveint
);
705 if (savepipe
!= SIG_IGN
)
706 safe_signal(SIGPIPE
, savepipe
);
715 pop3_exit(struct mailbox
*mp
)
720 POP3_OUT(rv
, "QUIT" NETNL
, MB_COMD
, goto jleave
);
721 POP3_ANSWER(rv
, goto jleave
);
728 pop3_delete(struct mailbox
*mp
, int n
)
734 snprintf(o
, sizeof o
, "DELE %u" NETNL
, n
);
735 POP3_OUT(rv
, o
, MB_COMD
, goto jleave
);
736 POP3_ANSWER(rv
, goto jleave
);
743 pop3_update(struct mailbox
*mp
)
746 int dodel
, c
, gotcha
, held
;
749 if (!(n_pstate
& n_PS_EDIT
)) {
752 for (m
= message
; PTRCMP(m
, <, message
+ msgCount
); ++m
)
753 if (m
->m_flag
& MBOX
)
760 for (m
= message
; PTRCMP(m
, <, message
+ msgCount
); ++m
) {
761 if (n_pstate
& n_PS_EDIT
)
762 dodel
= m
->m_flag
& MDELETED
;
764 dodel
= !((m
->m_flag
& MPRESERVE
) || !(m
->m_flag
& MTOUCH
));
766 pop3_delete(mp
, PTR2SIZE(m
- message
+ 1));
775 dnq
= n_shexp_quote_cp(displayname
, FAL0
);
777 if (gotcha
&& (n_pstate
& n_PS_EDIT
)) {
778 fprintf(n_stdout
, _("%s "), dnq
);
779 fprintf(n_stdout
, (ok_blook(bsdcompat
) || ok_blook(bsdmsgs
))
780 ? _("complete\n") : _("updated\n"));
781 } else if (held
&& !(n_pstate
& n_PS_EDIT
)) {
783 fprintf(n_stdout
, _("Held 1 message in %s\n"), dnq
);
785 fprintf(n_stdout
, _("Held %d messages in %s\n"), held
, dnq
);
796 sighandler_type
volatile saveint
, savepipe
;
797 enum okay
volatile rv
= STOP
;
802 if ((saveint
= safe_signal(SIGINT
, SIG_IGN
)) != SIG_IGN
)
803 safe_signal(SIGINT
, &_pop3_maincatch
);
804 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
805 if (sigsetjmp(_pop3_jmp
, 1) == 0) {
806 if (savepipe
!= SIG_IGN
)
807 safe_signal(SIGPIPE
, pop3catch
);
809 rv
= pop3_noop1(&mb
);
811 safe_signal(SIGINT
, saveint
);
812 safe_signal(SIGPIPE
, savepipe
);
819 pop3_setfile(char const *who
, char const *server
, enum fedit_mode fm
)
822 sighandler_type saveint
, savepipe
;
828 if (fm
& FEDIT_NEWMAIL
)
832 if (!url_parse(&sc
.sc_url
, CPROTO_POP3
, server
))
834 if (!ok_blook(v15_compat
) &&
835 (!(sc
.sc_url
.url_flags
& n_URL_HAD_USER
) ||
836 sc
.sc_url
.url_pass
.s
!= NULL
)) {
837 n_err(_("New-style URL used without *v15-compat* being set\n"));
841 if (!(ok_blook(v15_compat
) ? ccred_lookup(&sc
.sc_cred
, &sc
.sc_url
)
842 : ccred_lookup_old(&sc
.sc_cred
, CPROTO_POP3
,
843 ((sc
.sc_url
.url_flags
& n_URL_HAD_USER
) ? sc
.sc_url
.url_eu_h_p
.s
844 : sc
.sc_url
.url_u_h_p
.s
))))
850 if (!sopen(&sc
.sc_sock
, &sc
.sc_url
))
855 if (fm
& FEDIT_SYSBOX
)
856 n_pstate
&= ~n_PS_EDIT
;
858 n_pstate
|= n_PS_EDIT
;
859 if (mb
.mb_sock
.s_fd
>= 0)
870 initbox(sc
.sc_url
.url_p_u_h_p
);
871 mb
.mb_type
= MB_VOID
;
873 mb
.mb_sock
= sc
.sc_sock
;
875 saveint
= safe_signal(SIGINT
, SIG_IGN
);
876 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
877 if (sigsetjmp(_pop3_jmp
, 1)) {
879 n_err(_("POP3 connection closed\n"));
880 safe_signal(SIGINT
, saveint
);
881 safe_signal(SIGPIPE
, savepipe
);
888 if (saveint
!= SIG_IGN
)
889 safe_signal(SIGINT
, pop3catch
);
890 if (savepipe
!= SIG_IGN
)
891 safe_signal(SIGPIPE
, pop3catch
);
893 if ((cp
= xok_vlook(pop3_keepalive
, &sc
.sc_url
, OXM_ALL
)) != NULL
) {
894 n_idec_si32_cp(&_pop3_keepalive
, cp
, 10, NULL
);
895 if (_pop3_keepalive
> 0) {
896 _pop3_savealrm
= safe_signal(SIGALRM
, pop3alarm
);
897 alarm(_pop3_keepalive
);
901 mb
.mb_sock
.s_desc
= (sc
.sc_url
.url_flags
& n_URL_TLS_REQUIRED
)
903 mb
.mb_sock
.s_onclose
= pop3_timer_off
;
904 if (_pop3_login(&mb
, &sc
) != OKAY
||
905 pop3_stat(&mb
, &mailsize
, &msgCount
) != OKAY
) {
908 safe_signal(SIGINT
, saveint
);
909 safe_signal(SIGPIPE
, savepipe
);
915 mb
.mb_type
= MB_POP3
;
916 mb
.mb_perm
= ((n_poption
& n_PO_R_FLAG
) || (fm
& FEDIT_RDONLY
))
918 pop3_setptr(&mb
, &sc
);
920 /*if (!(fm & FEDIT_NEWMAIL)) */{
921 n_pstate
&= ~n_PS_SAW_COMMAND
;
922 n_pstate
|= n_PS_SETFILE_OPENED
;
925 safe_signal(SIGINT
, saveint
);
926 safe_signal(SIGPIPE
, savepipe
);
929 if ((n_poption
& (n_PO_EXISTONLY
| n_PO_HEADERLIST
)) == n_PO_EXISTONLY
) {
930 rv
= (msgCount
== 0);
934 if (!(n_pstate
& n_PS_EDIT
) && msgCount
== 0) {
935 if (!ok_blook(emptystart
))
936 n_err(_("No mail for %s at %s\n"), who
, sc
.sc_url
.url_p_eu_h_p
);
947 pop3_header(struct message
*m
)
952 /* TODO no URL here, no OXM possible; (however it is used in setfile()..) */
953 rv
= pop3_get(&mb
, m
, (ok_blook(pop3_bulk_load
) ? NEED_BODY
: NEED_HEADER
));
959 pop3_body(struct message
*m
)
964 rv
= pop3_get(&mb
, m
, NEED_BODY
);
970 pop3_quit(bool_t hold_sigs_on
)
972 sighandler_type
volatile saveint
, savepipe
;
981 if (mb
.mb_sock
.s_fd
< 0) {
982 n_err(_("POP3 connection already closed\n"));
988 saveint
= safe_signal(SIGINT
, SIG_IGN
);
989 savepipe
= safe_signal(SIGPIPE
, SIG_IGN
);
990 if (sigsetjmp(_pop3_jmp
, 1)) {
991 safe_signal(SIGINT
, saveint
);
992 safe_signal(SIGPIPE
, savepipe
);
997 if (saveint
!= SIG_IGN
)
998 safe_signal(SIGINT
, pop3catch
);
999 if (savepipe
!= SIG_IGN
)
1000 safe_signal(SIGPIPE
, pop3catch
);
1003 sclose(&mb
.mb_sock
);
1004 safe_signal(SIGINT
, saveint
);
1005 safe_signal(SIGPIPE
, savepipe
);
1015 #endif /* HAVE_POP3 */