diff options
Diffstat (limited to '')
-rw-r--r-- | imbox.1 | 6 | ||||
-rw-r--r-- | imbox.c | 66 |
2 files changed, 69 insertions, 3 deletions
diff --git a/imbox.1 b/imbox.1 index c91abd8..a1efa90 100644 --- a/imbox.1 +++ b/imbox.1 @@ -67,7 +67,9 @@ Connect to IMAP on .Ar host . The default host is determined by SRV record lookup on the domain name of -.Ar user . +.Ar user , +or simply the domain name +if no SRV record exists. . .It Fl m Ar mailbox Export messages from @@ -95,7 +97,7 @@ Read the password from standard input. . .Sh EXAMPLES .Bd -literal -imbox june@causal.agency | git am +imbox -T list@example.org june@causal.agency | git am .Ed . .Sh SEE ALSO diff --git a/imbox.c b/imbox.c index 0328c34..f2c65e8 100644 --- a/imbox.c +++ b/imbox.c @@ -26,6 +26,14 @@ #include <tls.h> #include <unistd.h> +#ifndef DIG_PATH +# ifdef __FreeBSD__ +# define DIG_PATH "/usr/bin/drill" +# else +# define DIG_PATH "dig" +# endif +#endif + static void compile(regex_t *regex, const char *pattern) { if (regex->re_nsub) return; int error = regcomp(regex, pattern, REG_EXTENDED | REG_NEWLINE); @@ -83,6 +91,56 @@ static void mboxrd(const char *headers, const char *body) { #undef MATCH } +static void lookup(const char **host, const char **port, const char *domain) { + static char buf[1024]; + snprintf(buf, sizeof(buf), "_imaps._tcp.%s", domain); + + int rw[2]; + int error = pipe(rw); + if (error) err(EX_OSERR, "pipe"); + + pid_t pid = fork(); + if (pid < 0) err(EX_OSERR, "fork"); + + if (!pid) { + close(rw[0]); + dup2(rw[1], STDOUT_FILENO); + dup2(rw[1], STDERR_FILENO); + close(rw[1]); + execlp(DIG_PATH, DIG_PATH, "-t", "SRV", "-q", buf, "+short", NULL); + err(EX_CONFIG, "%s", DIG_PATH); + } + + int status; + pid = wait(&status); + if (pid < 0) err(EX_OSERR, "wait"); + + close(rw[1]); + FILE *pipe = fdopen(rw[0], "r"); + if (!pipe) err(EX_IOERR, "fdopen"); + + fgets(buf, sizeof(buf), pipe); + if (ferror(pipe)) err(EX_IOERR, "fgets"); + fclose(pipe); + + if (!WIFEXITED(status) || WEXITSTATUS(status)) { + fprintf(stderr, "%s", buf); + exit(WEXITSTATUS(status)); + } + + char *ptr = buf; + char *dot = strrchr(ptr, '.'); + if (dot) *dot = '\0'; + strsep(&ptr, " \n"); // priority + strsep(&ptr, " \n"); // weight + *port = strsep(&ptr, " \n"); + *host = strsep(&ptr, " \n"); + if (!*host) { + *host = domain; + *port = "imaps"; + } +} + static bool verbose; int tlsRead(void *_tls, char *ptr, int len) { @@ -165,7 +223,7 @@ static char *readLiteral(FILE *imap, const char *line) { } int main(int argc, char *argv[]) { - const char *host = "imap.fastmail.com"; + const char *host = NULL; const char *port = "imaps"; const char *mailbox = "INBOX"; const char *subject = "[PATCH"; @@ -193,6 +251,12 @@ int main(int argc, char *argv[]) { const char *user = argv[optind]; if (!user) errx(EX_USAGE, "username required"); + if (!host) { + const char *domain = strchr(user, '@'); + if (!domain) errx(EX_USAGE, "no domain in username"); + lookup(&host, &port, &domain[1]); + } + char buf[1024]; char *pass = readpassphrase( (rppFlags & RPP_STDIN ? "" : "Password: "), |