diff -ru a/configure.ac b/configure.ac
--- a/configure.ac	2006-11-19 13:28:48.000000000 -0500
+++ b/configure.ac	2007-01-06 19:03:47.000000000 -0500
@@ -94,6 +94,17 @@
 AM_GNU_GETTEXT_VERSION(0.14.3)
 dnl end i18n
 
+# libpwmd support.
+AC_ARG_ENABLE(libpwmd,
+	[  --enable-libpwmd        compile with libpwmd support],,[enable_libpwmd=no])
+
+if test "$enable_libpwmd" = "yes"; then
+    AC_CHECK_LIB(pwmd, pwmd_connect,, AC_MSG_ERROR([libpwmd not found]))
+    AC_DEFINE(HAVE_LIBPWMD, 1, [Define if you have libpwmd installed.])
+    LDFLAGS="$LDFLAGS -L/usr/local/lib -lpwmd"
+    CFLAGS="$CFLAGS -I/usr/local/include"
+fi
+
 # Under sysV68, socket and friends are provided by the C library.
 # -linet does not provide socket, but causes multiple definition
 # errors at link-time.  It is thus better to only use the C library.
diff -ru a/fetchmail.c b/fetchmail.c
--- a/fetchmail.c	2006-09-18 05:04:15.000000000 -0400
+++ b/fetchmail.c	2007-01-06 19:01:10.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * fetchmail.c -- main driver module for fetchmail
+ r fetchmail.c -- main driver module for fetchmail
  *
  * For license terms, see the file COPYING in this directory.
  */
@@ -140,6 +140,24 @@
 
 const char *iana_charset;
 
+#ifdef HAVE_LIBPWMD
+void exit_with_pwmd_error()
+{
+    if (pwmd_ret == PWMD_PERROR) {
+	fprintf(stderr, GT_("pwmd: %s\n"), pwmd_strerror(pwmd_error));
+	exit(PS_AUTHFAIL);
+    }
+    else if (pwmd_ret == PWMD_AGENT_ERROR) {
+	fprintf(stderr, GT_("pwmd: gpg-agent error. Is GPG_AGENT_INFO set? Read gpg-agent(1) for more info.\n"));
+	exit(PS_AUTHFAIL);
+    }
+    else
+	fprintf(stderr, GT_("pwmd: %s\n"), strerror(pwmd_error));
+
+    exit(PS_UNDEFINED);
+}
+#endif
+
 int main(int argc, char **argv)
 {
     int bkgd = FALSE;
@@ -264,6 +282,9 @@
 #ifdef ENABLE_NLS
 	"+NLS"
 #endif /* ENABLE_NLS */
+#ifdef HAVE_LIBPWMD
+	"+PWMD"
+#endif
 	".\n";
 	printf(GT_("This is fetchmail release %s"), VERSION);
 	fputs(features, stdout);
@@ -284,8 +305,64 @@
     }
 
     /* avoid parsing the config file if all we're doing is killing a daemon */
-    if (!quitonly)
+    if (!quitonly) {
+#ifdef HAVE_LIBPWMD
+	/*
+	 * We need to connect to the server here before load_params is called.
+	 */
+	if (pwmd_file) {
+	    /*
+	     * Cannot get an element path without a service.
+	     */
+	    if (cmd_opts.server.protocol == 0 || cmd_opts.server.protocol == 1) {
+		fprintf(stderr, GT_("Option --pwmd-file needs a service (-p) parameter.\n"));
+		exit(PS_SYNTAX);
+	    }
+
+	    /*
+	     * Try and connect to pwmd.
+	     */
+	    if ((pwm = pwmd_connect(pwmd_socket, &pwmd_error)) == NULL)
+		exit_with_pwmd_error();
+
+	    /*
+	     * Use gpg-agent for password retrieval. In version 0.3 of pwmd
+	     * there is an option to push files into the file cache when the
+	     * daemon starts up. For a daemonized fetchmail, this may be
+	     * required because there won't be a way to get the key without a
+	     * tty.
+	     */
+	    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error, PWMD_SETOPT,
+			    PWMD_OPTION_USEAGENT, 1)) != PWMD_OK)
+		exit_with_pwmd_error();
+
+	    /*
+	     * Set the text to be used in the pinentry dialog.
+	     */
+	    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error, PWMD_SETOPT,
+			    PWMD_OPTION_TITLE, "Fetchmail")) != PWMD_OK)
+		exit_with_pwmd_error();
+
+	    snprintf(pwmd_buf, sizeof(pwmd_buf), 
+		    "A password is needed to open the file \"%s\".", pwmd_file);
+
+	    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error, PWMD_SETOPT,
+			    PWMD_OPTION_DESC, pwmd_buf)) != PWMD_OK)
+		exit_with_pwmd_error();
+
+	    /*
+	     * Try and open the file so we can later get account/server credentials. If
+	     * the file is not cached on the server, gpg-agent will ask for the
+	     * password.
+	     */
+	    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error, PWMD_OPEN,
+			    pwmd_file)) != PWMD_OK)
+		exit_with_pwmd_error();
+	}
+#endif
+
 	implicitmode = load_params(argc, argv, optind);
+    }
 
 #if defined(HAVE_SYSLOG)
     /* logging should be set up early in case we were restarted from exec */
@@ -510,6 +587,30 @@
 	if (ctl->active && !(implicitmode && ctl->server.skip)
 		&& !NO_PASSWORD(ctl) && !ctl->password)
 	{
+#ifdef HAVE_LIBPWMD
+	    /*
+	     * Try and find the account. The element tree must be in the form
+	     * of: account->password
+	     */
+	    if (pwm) {
+		snprintf(pwmd_buf, sizeof(pwmd_buf), "%s\tpassword", pwmd_account);
+		
+		if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+				PWMD_GET, pwmd_buf)) != PWMD_OK) {
+		    if (pwmd_ret == PWMD_ERROR)
+			fprintf(stderr, GT_("pwmd: %s\n"), strerror(pwmd_error));
+		    else if (pwmd_ret == PWMD_PERROR)
+			fprintf(stderr, GT_("pwmd (password): %s"), 
+				pwmd_strerror(pwmd_error));
+		}
+		else {
+		    ctl->password = xstrdup((char *)pwmd_result);
+		    memset(pwmd_result, 0, strlen((char *)pwmd_result));
+		    free(pwmd_result);
+		    continue;
+		}
+	    }
+#endif
 	    if (!isatty(0))
 	    {
 		fprintf(stderr,
@@ -529,6 +630,15 @@
 	}
     }
 
+#ifdef HAVE_LIBPWMD
+    /*
+     * We should have all the needed data from the server, go ahead and close
+     * the connection.
+     */
+    if (pwm)
+	pwmd_close(pwm);
+#endif
+
     /*
      * Time to initiate the SOCKS library (this is not mandatory: it just
      * registers the correct application name for logging purpose. If you
@@ -865,7 +975,7 @@
 	exit(PS_NOMAIL);
 }
 
-static void list_merge(struct idlist **dstl, struct idlist **srcl, int force)
+void list_merge(struct idlist **dstl, struct idlist **srcl, int force)
 {
     /*
      * If force is off, modify dstl fields only when they're empty (treat srcl
@@ -880,7 +990,7 @@
     }
 }
 
-static void optmerge(struct query *h2, struct query *h1, int force)
+void optmerge(struct query *h2, struct query *h1, int force)
 /* merge two options records */
 {
     list_merge(&h2->server.localdomains, &h1->server.localdomains, force);
@@ -960,16 +1070,40 @@
 #undef FLAG_MERGE
 }
 
+#ifdef HAVE_LIBPWMD
+char *protocol_to_service(int protocol)
+{
+    switch (protocol) {
+	case P_POP2:
+	    return "POP2";
+	case P_POP3:
+	    return "POP3";
+	case P_APOP:
+	    return "APOP";
+	case P_RPOP:
+	    return "RPOP";
+	case P_ETRN:
+	    return "ETRN";
+	case P_ODMR:
+	    return "ODMR";
+	default:
+	    return NULL;
+    }
+
+    return NULL;
+}
+#endif
+
 /** Load configuration files.
  * \return - true if no servers found on the command line
  *         - false if servers found on the command line */
-static int load_params(int argc, char **argv, int optind)
+int load_params(int argc, char **argv, int optind)
 {
     int	implicitmode, st;
     struct passwd *pw;
     struct query def_opts, *ctl;
     struct stat rcstat;
-    char *p;
+    char *p, *prot;
 
     run.bouncemail = TRUE;
     run.spambounce = FALSE;	/* don't bounce back to innocent bystanders */
@@ -1049,8 +1183,112 @@
 		 * call later on.
 		 */
 		ctl = hostalloc((struct query *)NULL);
+#ifdef HAVE_LIBPWMD
+		if (pwm) {
+		    prot = protocol_to_service(cmd_opts.server.protocol);
+		    pwmd_account = xstrdup(argv[optind]);
+
+		    /*
+		     * Get the hostname for this protocol. Element path must
+		     * be account->[protocol]->hostname.
+		     */
+		    snprintf(pwmd_buf, sizeof(pwmd_buf), "%s\t%s\thostname", pwmd_account, prot);
+
+		    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+				    PWMD_GET, pwmd_buf)) != PWMD_OK)
+			exit_with_pwmd_error();
+
+		    ctl->server.via =
+			ctl->server.pollname = xstrdup((char *)pwmd_result);
+		    memset(pwmd_result, 0, strlen((char *)pwmd_result));
+		    free(pwmd_result);
+
+		    /*
+		     * Get the remote username. Element must be
+		     * account->username.
+		     */
+		    snprintf(pwmd_buf, sizeof(pwmd_buf), "%s\tusername", pwmd_account);
+
+		    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+				    PWMD_GET, pwmd_buf)) != PWMD_OK)
+			exit_with_pwmd_error();
+
+		    def_opts.remotename = xstrdup((char *)pwmd_result);
+		    def_opts.server.esmtp_name = xstrdup(def_opts.remotename);
+		    memset(pwmd_result, 0, strlen((char *)pwmd_result));
+		    free(pwmd_result);
+
+		    /*
+		     * If there is a ssl element and set to 1, enable ssl for
+		     * this account. Element path must be
+		     * account->[protocol]->ssl.
+		     */
+		    snprintf(pwmd_buf, sizeof(pwmd_buf), "%s\t%s\tssl", pwmd_account, prot);
+
+		    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+				    PWMD_GET, pwmd_buf)) != PWMD_OK) {
+			if (pwmd_ret != PWMD_PERROR)
+			    exit_with_pwmd_error();
+			else
+			    fprintf(stderr, GT_("pwmd (ssl): %s"), pwmd_strerror(pwmd_error));
+		    }
+		    else {
+			p = xstrdup((char *)pwmd_result);
+			ctl->use_ssl = atoi(p);
+			memset(pwmd_result, 0, strlen((char *)pwmd_result));
+			free(pwmd_result);
+			free(p);
+		    }
+
+		    /*
+		     * account->[protocol]->sslfingerprint.
+		     */
+		    snprintf(pwmd_buf, sizeof(pwmd_buf), "%s\t%s\tsslfingerprint", 
+			    pwmd_account, prot);
+
+		    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+				    PWMD_GET, pwmd_buf)) != PWMD_OK) {
+			if (pwmd_ret != PWMD_PERROR)
+			    exit_with_pwmd_error();
+			else
+			    fprintf(stderr, GT_("pwmd (sslfingerprint): %s"), 
+					pwmd_strerror(pwmd_error));
+		    }
+		    else {
+			p = xstrdup((char *)pwmd_result);
+			ctl->sslfingerprint = p;
+			memset(pwmd_result, 0, strlen((char *)pwmd_result));
+			free(pwmd_result);
+		    }
+
+		    /*
+		     * Server port. Element path must be
+		     * account->[protocol]->port.
+		     */
+		    snprintf(pwmd_buf, sizeof(pwmd_buf), "%s\t%s\tport", pwmd_account, prot);
+
+		    if ((pwmd_ret = pwmd_command(pwm, &pwmd_result, &pwmd_error,
+				    PWMD_GET, pwmd_buf)) != PWMD_OK) {
+			if (pwmd_ret != PWMD_PERROR)
+			    exit_with_pwmd_error();
+			else
+			    fprintf(stderr, GT_("pwmd (port): %s"), 
+					pwmd_strerror(pwmd_error));
+		    }
+		    else {
+			p = xstrdup((char *)pwmd_result);
+			ctl->server.service = p;
+			memset(pwmd_result, 0, strlen((char *)pwmd_result));
+			free(pwmd_result);
+		    }
+		}
+		else
+		    ctl->server.via =
+			ctl->server.pollname = xstrdup(argv[optind]);
+#else
 		ctl->server.via =
 		    ctl->server.pollname = xstrdup(argv[optind]);
+#endif
 		ctl->active = TRUE;
 		ctl->server.lead_server = (struct hostdata *)NULL;
 	    }
diff -ru a/fetchmail.h b/fetchmail.h
--- a/fetchmail.h	2006-11-01 16:56:18.000000000 -0500
+++ b/fetchmail.h	2007-01-06 18:52:56.000000000 -0500
@@ -39,6 +39,10 @@
 #  include "trio/trio.h"
 #endif
 
+#ifdef HAVE_LIBPWMD
+#include <libpwmd.h>
+#endif
+
 /* We need this for strstr */
 #if !defined(HAVE_STRSTR) && !defined(strstr)
 char *strstr(const char *, const char *);
@@ -456,6 +460,16 @@
 extern char *sdps_envfrom;
 extern char *sdps_envto;
 #endif /* SDPS_ENABLE */
+#ifdef HAVE_LIBPWMD
+pwm_t *pwm;			/* the handle */
+char *pwmd_account;		/* the account being processed */
+char *pwmd_socket;		/* socket to connect to */
+char *pwmd_file;		/* file to open on server */
+void *pwmd_result;		/* server result */
+int pwmd_error;			/* protocol or errno */
+int pwmd_ret;			/* return value from pwmd_command() */
+char pwmd_buf[LINE_MAX];	/* element copy buffer */
+#endif
 
 extern const char *iana_charset;	/* IANA assigned charset name */
 
diff -ru a/options.c b/options.c
--- a/options.c	2006-08-14 19:04:02.000000000 -0400
+++ b/options.c	2007-01-06 18:52:56.000000000 -0500
@@ -54,11 +54,20 @@
 };
 
 /* options still left: CgGhHjJoORTWxXYz */
+#ifndef HAVE_LIBPWMD
 static const char *shortoptions = 
 	"?Vcsvd:NqL:f:i:p:UP:A:t:E:Q:u:akKFnl:r:S:Z:b:B:e:m:I:M:yw:D:";
+#else
+static const char *shortoptions = 
+	"C:G:?Vcsvd:NqL:f:i:p:UP:A:t:E:Q:u:akKFnl:r:S:Z:b:B:e:m:I:M:yw:D:";
+#endif
 
 static const struct option longoptions[] = {
 /* this can be const because all flag fields are 0 and will never get set */
+#ifdef HAVE_LIBPWMD
+  {"pwmd-socket",	required_argument,	   (int *) 0, 'C' },
+  {"pwmd-file",	required_argument,	   (int *) 0, 'G' },
+#endif
   {"help",	no_argument,	   (int *) 0, '?' },
   {"version",	no_argument,	   (int *) 0, 'V' },
   {"check",	no_argument,	   (int *) 0, 'c' },
@@ -286,6 +295,14 @@
 	    xfree(rcfile);
 	    rcfile = prependdir (optarg, currentwd);
 	    break;
+#ifdef HAVE_LIBPWMD
+	case 'C':
+	    pwmd_socket = xstrdup(optarg);
+	    break;
+	case 'G':
+	    pwmd_file = xstrdup(optarg);
+	    break;
+#endif
 	case 'i':
 	    rctl->idfile = prependdir (optarg, currentwd);
 	    break;
@@ -628,6 +645,10 @@
 	P(GT_("      --principal   mail service principal\n"));
 	P(GT_("      --tracepolls  add poll-tracing information to Received header\n"));
 
+#ifdef HAVE_LIBPWMD
+	P(GT_("  -C, --pwmd-socket pwmd socket path (~/.pwmd/socket)\n"));
+	P(GT_("  -G, --pwmd-file   filename to open on the pwmd server\n"));
+#endif
 	P(GT_("  -u, --username    specify users's login on server\n"));
 	P(GT_("  -a, --[fetch]all  retrieve old and new messages\n"));
 	P(GT_("  -K, --nokeep      delete new messages after retrieval\n"));
