44 |
45 |
46 |
--------------------------------------------------------------------------------
/SQL/postgres.initial.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE fetchmail (
2 | id integer NOT NULL,
3 | mailbox character varying(255) DEFAULT ''::character varying NOT NULL,
4 | active BOOLEAN DEFAULT 't' NOT NULL,
5 | src_server character varying(255) DEFAULT ''::character varying NOT NULL,
6 | src_auth character varying(15) DEFAULT 'password'::character varying NOT NULL,
7 | src_user character varying(255) DEFAULT ''::character varying NOT NULL,
8 | src_password character varying(255) DEFAULT ''::character varying NOT NULL,
9 | src_folder character varying(255) DEFAULT ''::character varying NOT NULL,
10 | poll_time integer DEFAULT 10 NOT NULL,
11 | fetchall BOOLEAN DEFAULT 'f' NOT NULL,
12 | keep BOOLEAN DEFAULT 't' NOT NULL,
13 | protocol character varying(15) DEFAULT 'IMAP'::character varying NOT NULL,
14 | usessl BOOLEAN DEFAULT 't' NOT NULL,
15 | sslcertck BOOLEAN DEFAULT 'f' NOT NULL,
16 | sslcertpath character varying(255) DEFAULT ''::character varying,
17 | sslfingerprint character varying(255) DEFAULT ''::character varying,
18 | extra_options text,
19 | returned_text text,
20 | mda character varying(255) DEFAULT ''::character varying NOT NULL,
21 | date timestamp with time zone DEFAULT now() NOT NULL
22 | CONSTRAINT fetchmail_protocol_check CHECK (((protocol)::text = ANY (ARRAY[('POP3'::character varying)::text, ('IMAP'::character varying)::text, ('POP2'::character varying)::text, ('ETRN'::character varying)::text, ('AUTO'::character varying)::text]))),
23 | CONSTRAINT fetchmail_src_auth_check CHECK (((src_auth)::text = ANY (ARRAY[('password'::character varying)::text, ('kerberos_v5'::character varying)::text, ('kerberos'::character varying)::text, ('kerberos_v4'::character varying)::text, ('gssapi'::character varying)::text, ('cram-md5'::character varying)::text, ('otp'::character varying)::text, ('ntlm'::character varying)::text, ('msn'::character varying)::text, ('ssh'::character varying)::text, ('any'::character varying)::text])))
24 | );
25 |
26 | CREATE SEQUENCE fetchmail_id_seq
27 | START WITH 1
28 | INCREMENT BY 1
29 | NO MINVALUE
30 | NO MAXVALUE
31 | CACHE 1;
32 |
33 | ALTER SEQUENCE fetchmail_id_seq OWNED BY fetchmail.id;
34 |
35 | ALTER TABLE ONLY fetchmail ALTER COLUMN id SET DEFAULT nextval('fetchmail_id_seq'::regclass);
36 |
37 | ALTER TABLE ONLY fetchmail ADD CONSTRAINT fetchmail_pkey PRIMARY KEY (id);
38 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Roundcube fetchmail plugin
2 |
3 | **Roundcube fetchmail plugin** is a **Roundcube** plugin, which allows users to download their mail from external mailboxes.
4 |
5 | ## Screenshot
6 | 
7 |
8 | ## Prerequisites
9 | 1. **Roundcube**
10 | 2. Database (**PostgreSQL** or **MySQL**)
11 | 3. **fetchmail** itself
12 | 4. **Postfix Admin** provides convenient `fetchmail.pl` script
13 |
14 | ## Installation
15 | Please follow these steps and adapt them to your distribution if necessary
16 |
17 | 1. First you need to install **fetchmail** itself. For **Debian** you can do so by `apt install fetchmail`
18 | 2. Next you should extract **Roundcube fetchmail plugin** archive into your **Roundcube** `plugins` folder creating "fetchmail" folder there.
19 | * You can do so either by using `composer` for which there is `composer.json`, still you need to follow further installation steps since those could not be accomplished with `composer`
20 | * Alternatively you can download needed release from [Releases page](https://github.com/PF4Public/fetchmail/releases) unpacking it accordingly
21 | 3. After that you need to enable newly installed plugin by adding it to **Roundcube** plugin list. For **Debian** related config file is `/etc/roundcube/main.inc.php` and relevant setting is
22 |
23 | ```php
24 |
25 | $rcmail_config ['plugins'] = array();
26 |
27 | ```
28 | Appending `, 'fetchmail'` to the list of plugins will suffice.
29 |
30 | 4. Unless default settings are suitable for you, you need to configure the plugin. See the [settings section](#settings) for more information.
31 | 5. You need to create additional table in your database using one of the supplied `.initial.sql` files and update it with all the dated `.sql` files accordingly. Another possibility is to use **Postfix Admin** table if you have it installed. If using **PostgreSQL** you may use schemas to share `fetchmail` table between **Roundcube** and **Postfix Admin**. Namely creating it in `public` schema, whereas every other table in it's appropriate schema, like `roundcube` and `postfixadmin`. Please refer to [the documentation](https://www.postgresql.org/docs/current/static/ddl-schemas.html) for more information. If you do so and use composer, however, you probably need to set the database version of this plugin in roundcube database to `9999999900` so that composer will not try updating it.
32 | 6. You will need `fetchmail.pl` script from **Postfix Admin** distribution. If you don't have **Postfix Admin** installed, you can obtain required `fetchmail.pl` script from their repo [postfixadmin / ADDITIONS / fetchmail.pl](https://github.com/postfixadmin/postfixadmin/blob/master/ADDITIONS/fetchmail.pl). But be sure to get at least revision [594a847](https://github.com/postfixadmin/postfixadmin/blob/594a847dcabc8c2d3e9b775f829df9763fbf776a/ADDITIONS/fetchmail.pl), at which support of `src_port` field introduced. Place it to where appropriate. For example, where your mailboxes are, e.g. `/var/mail`.
33 | 7. Next adapt `fetchmail.pl` to your config. Most likely you want to change these settings:
34 |
35 | ```perl
36 | # database backend - uncomment one of these
37 | our $db_type = 'Pg';
38 | #my $db_type = 'mysql';
39 |
40 | # host name
41 | our $db_host="127.0.0.1";
42 | # database name
43 | our $db_name="postfix";
44 | # database username
45 | our $db_username="mail";
46 | # database password
47 | our $db_password="CHANGE_ME!";
48 | ```
49 | Instead of changing this script, you may put your settings into `/etc/mail/postfixadmin/fetchmail.conf`
50 | 8. Next step is to configure **cron** for regular mail checking with `crontab -u mail -e`. For example for 5 minute intervals add this: `*/5 * * * * /var/mail/fetchmail.pl >/dev/null`. Worth noting that even if you configure cron for a 5 minutes interval, fetchmail will still abide user configured checking interval. As a result setting bigger intervals here manifests them as intervals available to fetchmail, that is setting `0 * * * *` here overrides any user setting wich is less then hour
51 | 9. You might also need to install `liblockfile-simple-perl` and either `libsys-syslog-perl` or `libunix-syslog-perl` on **Debian**-based systems.
52 | 10. Lastly there might be need to do `mkdir /var/run/fetchmail; chown mail:mail /var/run/fetchmail`
53 |
54 | Please note that some commands might require superuser permissions
55 |
56 | ## Settings
57 | In case you need to edit default-set settings, you may copy `config.inc.php.dist` to `config.inc.php` and edit settings as desired in the latter file, which will override defaults.
58 | * `$config['fetchmail_check_server']` if set to `true` the plugin will do a DNS lookup for the servername provided by the user. If the servername cannot be resolved in DNS, an error is displayed.
59 | * `$config['fetchmail_db_dsn']` allows you to use a fetchmail database outside the Roundcube database, e.g. from an existing Postfix Admin installation. see [Roundcube configuration options](https://github.com/roundcube/roundcubemail/wiki/Configuration#database-connection) for correct syntax. If set to `null`, Roundcube Database is used. Default is `null`.
60 | * `$config['fetchmail_folder']` whether to allow users to specify IMAP folder they wish to download mail from. Default is `false`.
61 | * `$config['fetchmail_limit']` limits the number of external mailboxes per user allowed. Default is `10`.
62 | * `$config['fetchmail_mda']` allows you to specify mda field for fetchmail. This could be useful in case you want to deliver downloaded mail via MDA or LDA directly, rather than forwarding via SMTP or LMTP. For more information please refer to [fetchmail manual](http://www.fetchmail.info/fetchmail-man.html) and [fetchmail.pl](https://github.com/postfixadmin/postfixadmin/blob/master/ADDITIONS/fetchmail.pl) script. Empty value here prevents any changes to this field in the database by the plugin, which may be useful if you need to control this field elsewhere. Default is `''`, i.e. empty.
63 |
64 | ## License
65 | This software distributed under the terms of the GNU General Public License as published by the Free Software Foundation
66 |
67 | Further details on the GPL license can be found at http://www.gnu.org/licenses/gpl.html
68 |
69 | By contributing to **Roundcube fetchmail plugin**, authors release their contributed work under this license
70 |
71 | ## Acknowledgements
72 | ### Original author
73 |
74 | Arthur Mayer, https://github.com/flames
75 |
76 | ### List of contributors
77 |
78 | For a complete list of contributors, refer to [Github project contributors page](https://github.com/PF4Public/fetchmail/graphs/contributors)
79 |
80 | #### Currently maintained by
81 | * [PF4Public](https://github.com/PF4Public)
82 |
--------------------------------------------------------------------------------
/fetchmail.js:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Fetchmail Roundcube Plugin (Roundcube version 1.0-beta and above)
3 | * This software distributed under the terms of the GNU General Public License
4 | * as published by the Free Software Foundation
5 | * Further details on the GPL license can be found at
6 | * http://www.gnu.org/licenses/gpl.html
7 | * By contributing authors release their contributed work under this license
8 | * For more information see README.md file
9 | ******************************************************************************/
10 | function fetchmail_on_change_protocol() {
11 | switch ($('#fetchmailprotocol').val()) {
12 | case "IMAP":
13 | $("#fetchmail_folder_display").show();
14 | break;
15 | default:
16 | $("#fetchmail_folder_display").hide();
17 | }
18 |
19 | switch ($('#fetchmailprotocol').val()) {
20 | case "IMAP":
21 | if ($("#fetchmailport").val() == 995 && $("#fetchmailusessl").prop('checked')) {
22 | $("#fetchmailport").val(993)
23 | } else if ($("#fetchmailport").val() == 110 && !$("#fetchmailusessl").prop('checked')) {
24 | $("#fetchmailport").val(143)
25 | }
26 | break;
27 | default:
28 | if ($("#fetchmailport").val() == 993 && $("#fetchmailusessl").prop('checked')) {
29 | $("#fetchmailport").val(995)
30 | } else if ($("#fetchmailport").val() == 143 && !$("#fetchmailusessl").prop('checked')) {
31 | $("#fetchmailport").val(110)
32 | }
33 | }
34 | }
35 | function fetchmail_on_change_ssl() {
36 | switch ($('#fetchmailprotocol').val()) {
37 | case "IMAP":
38 | if ($("#fetchmailport").val() == 143 && $("#fetchmailusessl").prop('checked')) {
39 | $("#fetchmailport").val(993)
40 | } else if ($("#fetchmailport").val() == 993 && !$("#fetchmailusessl").prop('checked')) {
41 | $("#fetchmailport").val(143)
42 | }
43 | break;
44 | default:
45 | if ($("#fetchmailport").val() == 110 && $("#fetchmailusessl").prop('checked')) {
46 | $("#fetchmailport").val(995)
47 | } else if ($("#fetchmailport").val() == 995 && !$("#fetchmailusessl").prop('checked')) {
48 | $("#fetchmailport").val(110)
49 | }
50 | }
51 | }
52 |
53 |
54 | if (window.rcmail) {
55 | rcmail.addEventListener('init', function (evt) {
56 | if (rcmail.env.action == 'plugin.fetchmail') {
57 | rcmail.section_select = function(list) {
58 | var win, id = list.get_single_selection();
59 |
60 | if (id && (win = this.get_frame_window(this.env.contentframe))) {
61 | this.location_href({_action: 'plugin.fetchmail.edit', _id: id, _framed: 1}, win, true);
62 | }
63 | this.enable_command('fetchmail.delete', true);
64 | }
65 |
66 | rcmail.register_command('fetchmail.delete', function() {
67 | var id = rcmail.sections_list.get_single_selection();
68 | rcmail.confirm_dialog(rcmail.get_label('fetchmail.fetchmaildelconfirm'), 'delete', function(e, ref) {
69 | var post = '_act=delete&_id=' + ref.sections_list.rows[id].uid,
70 | lock = ref.set_busy(true, 'loading');
71 |
72 | ref.http_post('plugin.fetchmail.delete', post, lock);
73 | });
74 | });
75 | rcmail.register_command('fetchmail.add', function() {
76 | if ((win = rcmail.get_frame_window(rcmail.env.contentframe))) {
77 | rcmail.location_href({_action: 'plugin.fetchmail.edit', _id: '', _framed: 1}, win, true);
78 | }
79 | rcmail.enable_command('fetchmail.delete', false);
80 | }, true);
81 |
82 | if(rcmail.sections_list.rowcount < rcmail.env.fetchmail_limit) {
83 | rcmail.enable_command('fetchmail.add', true);
84 | } else {
85 | rcmail.enable_command('fetchmail.add', false);
86 | }
87 |
88 | }
89 | if(rcmail.env.action == 'plugin.fetchmail.edit') {
90 | rcmail.register_command('fetchmail.save', function() {
91 | var form = document.getElementById('fetchmailform');
92 | $('#fetchmailform .invalid-feedback').remove();
93 | if(form.checkValidity()) {
94 | var settings = $('#fetchmailform').serialize();
95 | lock = rcmail.set_busy(true, 'loading');
96 | rcmail.http_post('plugin.fetchmail.save', settings, lock);
97 | }
98 | form.classList.add('was-validated');
99 | });
100 | rcmail.enable_command('fetchmail.save', true);
101 | }
102 | });
103 | rcmail.addEventListener('plugin.fetchmail.save.callback', function(e) {
104 | if(e.result == "done") {
105 | var rowid = "rcmrow"+e.id;
106 | if(parent.window.document.getElementById(rowid)) {
107 | parent.window.document.getElementById(rowid).getElementsByTagName('td')[0].innerText = e.title;
108 | } else {
109 | parent.window.rcmail.sections_list.insert_row({id:rowid,uid:e.id,className:"fetchmail-account",cols:[{className:"section",innerHTML:e.title}]});
110 | parent.window.rcmail.sections_list.select_row(e.id);
111 | }
112 | rcmail.display_message(rcmail.gettext('successfullysaved','fetchmail'), 'confirmation');
113 | if(parent.window.rcmail.sections_list.rowcount < parent.window.rcmail.env.fetchmail_limit) {
114 | parent.window.rcmail.enable_command('fetchmail.add', true);
115 | } else {
116 | parent.window.rcmail.enable_command('fetchmail.add', false);
117 | }
118 | parent.window.document.getElementById('fetchmail-quota').getElementsByClassName('count')[0].innerText = parent.window.rcmail.sections_list.rowcount+"/"+parent.window.rcmail.env.fetchmail_limit;
119 | parent.window.document.getElementById('fetchmail-quota').getElementsByClassName('value')[0].setAttribute("style","width:"+((parent.window.rcmail.sections_list.rowcount/parent.window.rcmail.env.fetchmail_limit)*100)+"%");
120 |
121 | } else if (e.result == "dnserror") {
122 | /* Override Client-Side Validation to display the DNS error properly, see https://github.com/twbs/bootstrap/issues/32733 */
123 | $('#fetchmailform').removeClass('was-validated');
124 | $('#fetchmailform input').addClass('is-valid');
125 | $('#fetchmailform select').addClass('is-valid');
126 | $('#fetchmailserver').removeClass('is-valid').addClass('is-invalid');
127 | const fb = document.createElement("div")
128 | fb.classList.add("invalid-feedback");
129 | fb.innerText = e.message;
130 | document.getElementById('fetchmailserver').parentNode.appendChild(fb);
131 | } else if (e.result == "dberror") {
132 | rcmail.display_message(e.message, 'error');
133 | }
134 | });
135 | rcmail.addEventListener('plugin.fetchmail.delete.callback', function(e) {
136 | if(e.result == "done") {
137 | rcmail.sections_list.remove_row(e.id);
138 | if ((win = rcmail.get_frame_window(rcmail.env.contentframe))) {
139 | win.location.href = rcmail.env.blankpage;
140 | }
141 | rcmail.display_message(rcmail.gettext('successfullydeleted','fetchmail'), 'confirmation');
142 | rcmail.enable_command('fetchmail.add', true);
143 | rcmail.enable_command('fetchmail.delete', false);
144 | document.getElementById('fetchmail-quota').getElementsByClassName('count')[0].innerText = rcmail.sections_list.rowcount+"/"+rcmail.env.fetchmail_limit;
145 | document.getElementById('fetchmail-quota').getElementsByClassName('value')[0].setAttribute("style","width:"+((rcmail.sections_list.rowcount/rcmail.env.fetchmail_limit)*100)+"%");
146 | } else if (e.result == "dberror") {
147 | rcmail.display_message(e.message, 'error');
148 | }
149 | });
150 |
151 | }
152 |
--------------------------------------------------------------------------------
/fetchmail.php:
--------------------------------------------------------------------------------
1 | rc = rcube::get_instance();
21 |
22 | $this->load_config('config.inc.php.dist');
23 | $this->load_config();
24 | $this->add_texts('localization/', true);
25 | $this->include_stylesheet($this->local_skin_path() .'/fetchmail.css');
26 | $this->show_folder = $this->rc->config->get('fetchmail_folder');
27 |
28 | $this->add_hook('settings_actions', [$this, 'settings_actions']);
29 |
30 | $this->register_action('plugin.fetchmail', [$this, 'init_html']);
31 | $this->register_action('plugin.fetchmail.edit', [$this, 'init_html']);
32 | $this->register_action('plugin.fetchmail.save', [$this, 'save']);
33 | $this->register_action('plugin.fetchmail.delete', [$this, 'delete']);
34 | }
35 |
36 | public function init_html()
37 | {
38 | $this->rc->output->set_pagetitle($this->gettext('fetchmail'));
39 | $this->include_script('fetchmail.js');
40 |
41 | if ($this->rc->action == 'plugin.fetchmail.edit') {
42 | $this->rc->output->add_handler('fetchmailform', [$this, 'gen_form']);
43 | $this->rc->output->send('fetchmail.fetchmailedit');
44 | } else {
45 | $this->rc->output->add_handler('sectionslist', [$this, 'section_list']);
46 | $this->rc->output->add_handler('fetchmail.quota', [$this, 'quota']);
47 | $this->rc->output->send('fetchmail.fetchmail');
48 | }
49 | }
50 |
51 | public function delete()
52 | {
53 | $this->_db_connect('w');
54 | $id = rcube_utils::get_input_value('_id', rcube_utils::INPUT_POST);
55 |
56 | if ($id != 0 || $id != '')
57 | {
58 | $sql = "DELETE FROM fetchmail WHERE id = '$id'";
59 | $delete = $this->db->query($sql);
60 | rcmail::get_instance()->output->command('plugin.fetchmail.delete.callback', array(
61 | 'result' => 'done',
62 | 'id' => $id
63 | ));
64 | }
65 | }
66 |
67 | public function quota($attrib)
68 | {
69 | $this->_db_connect('w');
70 | $mailbox = $this->rc->user->data['username'];
71 | $sql = "SELECT * FROM fetchmail WHERE mailbox='" . $mailbox . "'";
72 | $result = $this->db->query($sql);
73 | $limit = $this->rc->config->get('fetchmail_limit');
74 | $num_rows = $this->db->num_rows($result);
75 | $percent = ($num_rows / $limit) * 100;
76 | $out = "