如何使用 .Net 连接到 Mailman 邮件列表

发布于 2024-08-23 22:00:56 字数 106 浏览 5 评论 0原文

我必须开发一个 .Net 应用程序,在其中我必须从 Mailman 邮件列表中添加或删除用户。我的问题是是否有任何 .Net 连接器或 Dll 可以使用 .Net 连接到 mailman 邮件列表。

I have to develop a .Net application in which i have to add or remove a user from Mailman mailing list.My Question is whether there is any .Net connector or Dll to connect to mailman mailing list using .Net.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

汹涌人海 2024-08-30 22:00:56

编辑 (9/21/14): 我刚刚发布了一个 NuGet 包,用于通过 HTTP 调用操作 Mailman v2 列表的大部分方面。 https://www.nuget.org/packages/MailmanSharp/

我不知道任何现有组件都可以执行此操作,但由于 Mailman 界面全部位于 Web 上,因此您可以使用 HttpWebRequest“控制”它;我最近编写了一个小应用程序,它可以检索订阅者列表、订阅/取消订阅人员以及设置单独的标志,例如中等/无邮件/等。需要在 Mailman 页面的源代码中进行一些探索才能了解需要在 POST 中设置哪些变量,并进行一些试验和错误。我建议设置一个临时邮件列表来玩。

为了完成大部分工作,您需要一个持久的 CookieContainer,您可以将其连接到不同的 HttpWebRequest;第一个调用是使用管理员密码对管理页面进行 POST,以设置允许您访问其他页面的会话 cookie。

有些 POST 是常规的 application/x-www-form-urlencoded 类型,但有些也是 multipart/form-data。对于后者,我在 http://www. briangrinstead.com/blog/multipart-form-post-in-c 我必须进行一些更改,以便可以传入我的 CookieContainer

以下是一些示例代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Data;
using System.Threading;

namespace UpdateListserv
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                File.Delete(_logFilename);
                Log(String.Format("Starting: {0}", DateTime.Now));
                Login();
                var roster = GetSubscribers();
                Unsubscribe(roster);
                string members = GetMemberEmails();
                Subscribe(members); 
                Unmoderate("[email protected]");
                Log("Done");
            }

            catch(Exception e)
            {
                Log(e.Message);
            }
        }

        private static void Unmoderate(string email)
        {                
            Log("Unmoderating " + email);
            email = email.Replace("@", "%40");
            _vars.Clear();
            _vars["user"] = email;
            _vars[email + "_nomail"] = "off";
            _vars[email + "_nodupes"] = "on";
            _vars[email + "_plain"] = "on";
            _vars[email + "_language"] = "en";
            _vars["setmemberopts_btn"] = "Submit Your Changes";
            FormUpload.MultipartFormDataPost(_adminUrl + _membersPage, "foobar", _vars, _cookies);
        }

        private static CookieContainer _cookies = new CookieContainer();
        private static string _adminUrl = "http://mylist.com/admin.cgi/listname";
        private static string _rosterUrl = "http://mylist.com/roster.cgi/listname";
        private static string _pw = "myPassword";
        private static string _adminEmail = "[email protected]";
        private static Dictionary<string, object> _vars = new Dictionary<string, object>();

        private static string _addPage = "/members/add";
        private static string _removePage = "/members/remove";
        private static string _membersPage = "/members";

        private static string _logFilename = "Update Listserv.log";

        private static void Log(string message)
        {
            Console.WriteLine(message);
            using (var log = File.AppendText(_logFilename))
                log.WriteLine(message);
        }


        private static void Subscribe(string members)
        {
            // members is a list of email addresses separated by \n
            Log("Subscribing everyone");
            _vars.Clear();
            _vars["subscribees"] = members;
            _vars["subscribe_or_invite"] = 0;
            _vars["send_welcome_msg_to_this_batch"] = 0;
            _vars["send_notifications_to_list_owner"] = 0;
            FormUpload.MultipartFormDataPost(_adminUrl + _addPage, "foobar", _vars, _cookies);
        }

        private static string GetMemberEmails()
        {
            // This method retrieves a list of emails to be 
            // subscribed from an external source
            // and returns them as a string with \n in between.
        }

        private static void Unsubscribe(string roster)
        {
            // roster is a list of email addresses separated by \n
            Log("Unsubscribing everybody");
            _vars.Clear();
            _vars["unsubscribees"] = roster;
            _vars["send_unsub_ack_to_this_batch"] = 0;
            _vars["send_unsub_notifications_to_list_owner"] = 0;
            FormUpload.MultipartFormDataPost(_adminUrl + _removePage, "foobar", _vars, _cookies);
        }

        private static string GetSubscribers()
        {
            // returns a list of email addresses subscribed to the list,
            // separated by \n
            Log("Getting subscriber list");
            var req = GetWebRequest(_rosterUrl);
            req.Method = "post";
            _vars.Clear();
            _vars["roster-email"] = _adminEmail;
            _vars["roster-pw"] = _pw;

            var rosterLines = GetResponseString(req).Split('\n').Where(l => l.StartsWith("<li>"));
            Log(String.Format("Got {0} subscribers", rosterLines.Count()));

            var roster = new List<string>();
            var regex = new Regex("<a.*>(.*)</a>");

            foreach (var line in rosterLines)
            {
                roster.Add(regex.Match(line).Groups[1].Value.Replace(" at ", "@"));
            }

            return String.Join("\n", roster);
        }

        private static void Login()
        {
            Log("Logging in to list admin panel");
            var req = GetWebRequest(_adminUrl);
            req.Method = "post";
            _vars["adminpw"] = _pw;
            SetPostVars(req);
            req.GetResponse();
        }

        private static HttpWebRequest GetWebRequest(string url)
        {
            var result = HttpWebRequest.Create(url) as HttpWebRequest;
            result.AllowAutoRedirect = true;
            result.CookieContainer = _cookies;
            result.ContentType = "application/x-www-form-urlencoded";

            return result;
        }

        private static string GetResponseString(HttpWebRequest req)
        {
            using (var res = req.GetResponse())
            using (var stream = res.GetResponseStream())
            using (var sr = new StreamReader(stream))
            {
                return sr.ReadToEnd();
            }
        }

        private static void SetPostVars(HttpWebRequest req)
        {
            var list = _vars.Select(v => String.Format("{0}={1}", v.Key, v.Value));

            using (var stream = req.GetRequestStream())
            using (var writer = new StreamWriter(stream))
            {
                writer.Write(String.Join("&", list));
            }
        }
    }
}

Edit (9/21/14): I have just released a NuGet package for manipulating most aspects of a Mailman v2 list via HTTP calls. https://www.nuget.org/packages/MailmanSharp/

I'm not aware of any existing component to do this, but since the Mailman interface is all on the web, you can "control" it with HttpWebRequest; I recently wrote a small app which can retrieve the subscriber list, subscribe/unsubscribe people, and set individual flags like moderate/nomail/etc. It takes a little poking around in the source of the Mailman pages to see what variables need to be set in the POST, and some trial and error. I suggest setting up a temp Mailman list just to play with.

In order to do most of this, you'll need a persistent CookieContainer that you can hook up to your different HttpWebRequests; the first call is a POST to the admin page with the admin password to set the session cookie that gives you access to the other pages.

Some of the POSTs are regular application/x-www-form-urlencoded types, but some are also multipart/form-data. For the latter, I found some very helpful code at http://www.briangrinstead.com/blog/multipart-form-post-in-c I had to make a couple of changes so that I could pass in my CookieContainer

Here's some sample code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Data;
using System.Threading;

namespace UpdateListserv
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                File.Delete(_logFilename);
                Log(String.Format("Starting: {0}", DateTime.Now));
                Login();
                var roster = GetSubscribers();
                Unsubscribe(roster);
                string members = GetMemberEmails();
                Subscribe(members); 
                Unmoderate("[email protected]");
                Log("Done");
            }

            catch(Exception e)
            {
                Log(e.Message);
            }
        }

        private static void Unmoderate(string email)
        {                
            Log("Unmoderating " + email);
            email = email.Replace("@", "%40");
            _vars.Clear();
            _vars["user"] = email;
            _vars[email + "_nomail"] = "off";
            _vars[email + "_nodupes"] = "on";
            _vars[email + "_plain"] = "on";
            _vars[email + "_language"] = "en";
            _vars["setmemberopts_btn"] = "Submit Your Changes";
            FormUpload.MultipartFormDataPost(_adminUrl + _membersPage, "foobar", _vars, _cookies);
        }

        private static CookieContainer _cookies = new CookieContainer();
        private static string _adminUrl = "http://mylist.com/admin.cgi/listname";
        private static string _rosterUrl = "http://mylist.com/roster.cgi/listname";
        private static string _pw = "myPassword";
        private static string _adminEmail = "[email protected]";
        private static Dictionary<string, object> _vars = new Dictionary<string, object>();

        private static string _addPage = "/members/add";
        private static string _removePage = "/members/remove";
        private static string _membersPage = "/members";

        private static string _logFilename = "Update Listserv.log";

        private static void Log(string message)
        {
            Console.WriteLine(message);
            using (var log = File.AppendText(_logFilename))
                log.WriteLine(message);
        }


        private static void Subscribe(string members)
        {
            // members is a list of email addresses separated by \n
            Log("Subscribing everyone");
            _vars.Clear();
            _vars["subscribees"] = members;
            _vars["subscribe_or_invite"] = 0;
            _vars["send_welcome_msg_to_this_batch"] = 0;
            _vars["send_notifications_to_list_owner"] = 0;
            FormUpload.MultipartFormDataPost(_adminUrl + _addPage, "foobar", _vars, _cookies);
        }

        private static string GetMemberEmails()
        {
            // This method retrieves a list of emails to be 
            // subscribed from an external source
            // and returns them as a string with \n in between.
        }

        private static void Unsubscribe(string roster)
        {
            // roster is a list of email addresses separated by \n
            Log("Unsubscribing everybody");
            _vars.Clear();
            _vars["unsubscribees"] = roster;
            _vars["send_unsub_ack_to_this_batch"] = 0;
            _vars["send_unsub_notifications_to_list_owner"] = 0;
            FormUpload.MultipartFormDataPost(_adminUrl + _removePage, "foobar", _vars, _cookies);
        }

        private static string GetSubscribers()
        {
            // returns a list of email addresses subscribed to the list,
            // separated by \n
            Log("Getting subscriber list");
            var req = GetWebRequest(_rosterUrl);
            req.Method = "post";
            _vars.Clear();
            _vars["roster-email"] = _adminEmail;
            _vars["roster-pw"] = _pw;

            var rosterLines = GetResponseString(req).Split('\n').Where(l => l.StartsWith("<li>"));
            Log(String.Format("Got {0} subscribers", rosterLines.Count()));

            var roster = new List<string>();
            var regex = new Regex("<a.*>(.*)</a>");

            foreach (var line in rosterLines)
            {
                roster.Add(regex.Match(line).Groups[1].Value.Replace(" at ", "@"));
            }

            return String.Join("\n", roster);
        }

        private static void Login()
        {
            Log("Logging in to list admin panel");
            var req = GetWebRequest(_adminUrl);
            req.Method = "post";
            _vars["adminpw"] = _pw;
            SetPostVars(req);
            req.GetResponse();
        }

        private static HttpWebRequest GetWebRequest(string url)
        {
            var result = HttpWebRequest.Create(url) as HttpWebRequest;
            result.AllowAutoRedirect = true;
            result.CookieContainer = _cookies;
            result.ContentType = "application/x-www-form-urlencoded";

            return result;
        }

        private static string GetResponseString(HttpWebRequest req)
        {
            using (var res = req.GetResponse())
            using (var stream = res.GetResponseStream())
            using (var sr = new StreamReader(stream))
            {
                return sr.ReadToEnd();
            }
        }

        private static void SetPostVars(HttpWebRequest req)
        {
            var list = _vars.Select(v => String.Format("{0}={1}", v.Key, v.Value));

            using (var stream = req.GetRequestStream())
            using (var writer = new StreamWriter(stream))
            {
                writer.Write(String.Join("&", list));
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文