WikiBox

Summary: Allow posting to and reading from PmWiki via email
Version: 2008-08-17
Prerequisites: 2.2.x beta, PHP5
Status: Alpha
Maintainer: Peter Bowers
Users: +4 (View / Edit)
Download: wikibox.phpΔ

Questions answered by this recipe

This section is optional; use it to indicate the types of questions (if any) this recipe is intended to answer.

  • How can I post to wiki pages via email?
  • How can I upload a file by sending it as an attachment in an email?
  • How can I get the contents of a page (source or HTML) via email?

Description

Allow posting to and reading from PmWiki pages via email.

Hey! There's an ongoing alpha (actually probably it's up to beta by now) test going on over at www.qdk.org. If you're interested in taking part (or at least seeing what wikibox looks like in real life) feel free to check it out. You can send an email to wikibox@qdk.org with the subject "usage" to get a broad overview. Or you can go and visit http://www.qdk.org/pmwiki/pmwiki.php?n=WikiBox.WikiBox if you want to see a really quick overview of how the testing is organized, what pages are involved, etc.

Installation

include_once("$FarmD/cookbook/toolbox.php");
include_once("$FarmD/cookbook/SecLayer.php");
include_once("$FarmD/cookbook/wikibox.php");
include_once("$FarmD/cookbook/wikimail.php");
$wbModerator = 'moderator@localhost';  // replace this with the email address of the moderator
                                       // you can also make it an array of addresses if more than 1
# Normally this call to wmMkProfilePOP3() would be on a single line
wmMkProfilePOP3('wikibox', //name of the profile - must be wikibox unless you change $wbPOP3Profile
   'pop3.mydomain.com', // host where WikiBox will pick up mail
   'myusername',        // username WikiBox will use to pick up mail
   'secret');            // password WikiBox will use to pick up mail
# There are several other optional parameters you can also set in the profile, but these 3 usually suffice

Note the need to edit the moderator address from the current moderator@localhost to whatever you will use.

  • Create a page SiteAdmin.WikiBoxPageAuth giving authorization to the pages you are interested in. The following would give full permission to any files in the Test group:
all=overwrite,insert,create,read
edit = overwrite, create, insert

Test.*:all
  • Create a page SiteAdmin.WikiBoxEmailAuth defining at least 1 email address who will be a moderator (the email address must match what will be received in the "From" field of an email from this person and the "xyz" should be replaced with the wikibox-passwd for this person, a non-vital password used to verify)
moderator@localhost:::1:0:xyz::::::

Make SURE that you replace moderator@localhost above with the same address you used in $wbModerator above! And you might want a slightly better password than xyz, but that's up to you... :-)

  • Place the markup (:wikibox PROCESS verbose=2:) on a page (optional (:messages:) markup on the same page). You can choose whatever page you want, but WikiBox.Check is the standard.
    • You can make verbose be 1 or leave it out together - it depends how much information you want. (:messages:) gives lots of information (probably more debugging level) whereas verbose=2 is pretty reasonable and helpful.
  • Security defaults can be modified as follows (choose one of the latter 2 options if you don't like the default):
$wbControl['Write'] = array('Receive', 'UserConfirm','Moderate','Complete'); // default
$wbControl['Write'] = array('Receive', 'UserConfirm','Complete'); // no moderator requirement
$wbControl['Write'] = array('Receive', 'Complete'); // no moderator nor user confirmation requirement
  • You can also change $wbControl['Usage'], $wbControl['Subscribe'], $wbControl['Unsubscribe'], $wbControl['Blacklist'], $wbControl['Write'], and $wbControl['Read']
  • A finer degree of configuration control can be achieved by modifying the $wbRequire[] and $wbPrepFor[] arrays, but that'll have to be documented another day.
  • You will want to have your WikiBox.Check page loaded on a regular basis. For this you will need some way of automatically loading a web-page on a given schedule (i.e., every 10 minutes during work hours, every hour at night and during weekends - something like that). Cron and wget are tools in a linux environment which accomplish this admirably. To run the beta test at www.qdk.org I used this script (named /usr/local/bin/checkqdk and given executable privileges):
echo "Checking..."
wget -N --no-cache -E "http://www.qdk.org/pmwiki/pmwiki.php?n=WikiBox.Check" >/dev/null 2>&1
#sed -n -e 's/<[^>]*>//g' -e '/WIKIBOX PROCESSING/,/WIKIBOX COMPLETE/p' pmwiki.php\?n\=WikiBox.Check.html 

(The last line is useful if you are running it from the command line rather than through CRON -- if you remove the "#" at the start of that last line then it will give you a quick summary of the output of wikibox during the run.)

Then in /etc/crontab you would need entries like this:

# Every 15 minutes between 8am and 5pm Mon-Fri
0,15,30,45 8-17 * * 1-5 root /usr/local/bin/checkqdk
# Every 30 minutes before 8am and after 5pm Mon-Fri
0,30 0-8,17-23 * * 1-5 root /usr/local/bin/checkqdk
# Every hour on weekends
0 0-23 * * 6-7 root /usr/local/bin/checkqdk

Obviously you would need to determine what schedule worked for you.

Do note that while this cron job can be on the hosting server it by no means must be on that machine. You can run that script from a home machine, from your friend's machine that has linux on it, etc. The only requirements are (a) the machine has to keep running, (b) it has to be a machine with cron (usually linux although cygwin might have something for windows?) and (c) it has to have network access to your site (usually this means simply being connected to the internet).

Notes

Emails consist of a subject and the body of the email. For WikiBox the subject becomes a command specifying where and how the body of the email should be placed on a given page. The body of the email should be plaintext as it will be inserted into the page character-for-character as it appears in the body of the email.

Various valid initiating commands (placed in the subject) follow:

  • usage
    • No security or confirmation is required - a simple usage message will be returned by reply mail
  • subscribe
    • Security currently requires a user confirmation and a moderator confirmation
    • When all security requirements have been met then the original sending email will be added to SiteAdmin.WikiBoxEmailAuth
  • unsubscribe
    • Security currently requires a user confirmation
    • When all security requirements have been met then the original sending email will be marked as inactive in SiteAdmin.WikiBoxEmailAuth
  • blacklist
    • Security currently requires a user confirmation
    • When all security requirements have been met then the original sending email will be marked as blacklisted in SiteAdmin.WikiBoxEmailAuth
  • Write to [[Test.Foo]]
  • Overwrite [[Test.Foo]]
  • Append to [[Test.Foo]]
  • Prepend to [[Test.Foo]]
  • Insert into [[Test.Foo]] after /this pattern/i
  • Insert into [[Test.Foo]] before /this pattern/
  • Insert into [[Test.Foo]] replacing /this pattern/
  • Insert into [[Test.Foo]] instead of /this pattern/
    • Security for all write operations by default requires a user confirmation and a moderator confirmation
    • When all security requirements have been met then the body of the email will be written to the page specified in the location indicated
  • Read from [[Test.Foo]] ruleset=source|text|full fmt=html|text|both
    • Security for read operations by default requires appropriate password authentication on the initiating email
    • When all security requirements have been met then the page requested will be returned by return email
    • options of ruleset=x and fmt=x are optional
      • ruleset=source - return the unmodified source of the page
      • ruleset=text - run , (:comment:), and (:include:) rules so you get a better representation of the text of the page
      • ruleset=full - fun all markup rules (Better set fmt=html)

Each write command is made up of a main command, optional filler words, a pagename, and then (if the main command was "insert") a location and a pattern.

Main Write Commands

  • "Write" and "Overwrite" and "Replace" are synonyms. They will create a page if it doesn't exist or overwrite any existing content if the page already exists.
  • "Append" adds the body of the email at the end of any existing text in the page (or creates the page if it doesn't exist)
  • "Prepend" adds the body of the email prior to any existing text in the page (or creates the page if it doesn't exist)
  • "Insert" allows the placement of the text in the email body relative to some pattern in the existing text on the page. If "Insert" is the main command then you must specify a location sub-command and a pattern
    • Location Subcommand
      • "after" - find the pattern and insert the text immediately following
      • "before" - find the pattern and insert the text immediately prior to the pattern
      • "replacing" (or, synonymously, "instead of") replaces the pattern with the body of the email
    • Pattern
      • The pattern can be any valid regex that preg_match would accept. Pattern modifiers (i, m, s, etc.) are valid as well.
      • Patterns should be unique on the page or the text of the email body will be inserted multiple times, once for each time the pattern is matched.

Filler words

Filler words like "on", "in", "to", "into", "at the top of", "at the bottom of", etc between the main command and the name of the page are optional and ignored. They just make the command a little more readable. Do note that the filler words are really ignored. "Insert at the top of [[Page]]" is *not* the equivalent of "Prepend to [[Page]]" -- the former will still require a location subcommand and a pattern and the fact that you said "at the top of" will be completely ignored.

Page

The page must be specified as [[Group.Page]]. It is required. This is the page into which the text in the body of the email will be placed.

Email Body

Text only at the current time. I suppose it goes without saying, but markup is text, so any valid pmwiki markup can be placed in the body of the email.

If you send HTML or some other format email then only the text portion will be pulled out. If you want to format your page, put pmwiki markup in your text.

Attachments can be automatically uploaded to whatever page is being written to (only valid on a request that writes to a page). Simply follow these instructions:

  1. Attach the file, taking note of the exact spelling of the filename
  2. Include the text wikibox-attach:FILENAME on a line by itself in the body of your email (make sure you get the exact spelling and case of the filename). This line will not be written to the page, but it indicates that that attachment was something you intentionally wanted to upload.
  3. Often you will want to include an "Attach:FILENAME Δ" markup as well, but this is up to you -- it keeps you from having an "orphaned" upload with no links to it...
  4. Assuming your wikibox account has a password (as it should) then make sure you don't forget to specify that as well

Following the examples above, here is an email you could send with an attachment named "prettypicture.jpg":

SUBJECT: write to [[Test.ShowThePicture]]

wikibox-passwd:mysecretpass
wikibox-attach:prettypicture.jpg
Hey!  Take a look at this pretty picture!  Attach:prettypicture.jpg
(Everything below this line is just for fun to show the possibility that other markup can be included and written to 
the page -- the 1st 3 lines above, in combination with the subject and the attachment, are what are required to make 
uploading via attachment work.)
* and
** a
*** list
'''boldfaced''' and ''italicized'' text
[[Test.Link|+]] to put a link
and any other markup I would like to do

Markup / Usage

Wikibox does nothing until the page with the appropriate markup on it is loaded. The markup used is (:wikibox:) with possible arguments (notably (:wikibox PROCESS verbose=2:) which would be the norm). Currently emails will be processed only when this page is loaded ("PROCESS" is a required argument). Errors will be logged to SiteAdmin.WikiBoxErrorLog - this page should be checked periodically, particularly if you are not getting expected results. If you are really having trouble you can set $DebugLevel=2 and make sure (:messages:) markup exists on your page - then you'll need to attempt to work through the debug trace statements.

If you wish to place a signup form on a page somewhere (WikiBox.Signup is the standard and recommended) then simply create that page and place (:wikibox SIGNUP:) as the sole markup on that page. Users will then have the capability of going there to sign up for a wikibox account (as an alternative to sending a message to the main wikibox address for your site with the subject "subscribe" and then being moderated and etc.).

Note that the authorization of the user loading the page with the (:wikibox:) markup is irrelevant -- each email address is linked to a set of authorizations (passwords that are in memory at the time the user signed up through the form interface). Those authorizations (belonging to the email address user) will temporarily replace the authorizations of the real user who is loading the page. This makes it possible for an administrator to load the page without fear that an illicit operation might occur as well as allowing a privileged user to make changes (or request privileged reads) without requiring that the page be loaded by someone with those specific privileges.

Release Notes

If the recipe has multiple releases, then release notes can be placed here. Note that it's often easier for people to work with "release dates" instead of "version numbers".

  • 2008-08-17 Lots of little bug fixes and improvements. We've arrived at pretty good stability. Biggest change here is mime capability and thus capability of handling attachments and receiving HTML email. Also if the user signs up using the form interface a snapshot of their current authorizations will be made and that will be used for any future read/edit operations from that email address.
  • 2008-08-08 Release to keep in sync with wikimail. Other general improvements, bug fixes, etc.
  • 2008-08-02 Minor release to correspond with function namechange in wikimail. Realized documentation here is 2 versions back and completely wrong :-(
  • 2008-06-15 Implemented reject commands with deletion of inbox. Allow empty passwd to not be checked. Setting of expected sender for moderator.
  • 2008-06-12 Completely recoded, redesigned, etc. Still only plaintext email allowed and no attachment support. Much better granularity & configurability on security, etc.
  • 2008-05-18 Initial release. Only plaintext email allowed, no attachment support.

See Also

Contributors

Roadmap

  • Document how to run markup via cron so people can use that. (Is it just wget?)
  • Reimplement the form interface (no longer working)
    • In the form go on to the next page of messages automatically instead of requiring the user to click next.
  • Figure out SASL and document that.
  • Allow a validation on any header element (i.e., $ValidHeaders['from'] = array('me@mydomain.com', 'you@yourdomain.com');)
  • Allow a processing option of a few seconds each page-load (maybe once ever n seconds?) in addition to the form-based interface and the cron-based interface... This would work somewhat like the current processing of ImportText or updating the page cache.

Comments

In my config.php, the line calling wmMkProfilePOP3 seems to be problematic. My wiki goes blank and ceases to funtion (HTTP 500 Internal Server Error) when it is present. I have checked it several times and also used the lines copied directly out of this page - which, though incorrectly configured, should still produce a functional site. What could be wrong? How do I test it? DavidBessler February 27, 2009, at 08:49 AM

Are you with PHP5 or PHP4? PHP5 is a requirement for this recipe. Please drop me a line or leave me some way to get in touch with you and we can chase it down together... Peter Bowers February 27, 2009, at 02:06 PM

I figured it out. I'm using PHP5 on a standard godaddy hosting account, by the way. I turned on error reporting on my php5.ini file, and saw that php was not finding the cookbook files. I replaced the single quotes around the path names in the include_once statements in config.php with double quotes--like the rest of my include_once statements, and it worked. DavidBessler March 03, 2009, at 08:21 AM

You're absolutely right. I've fixed those in the example config above now.

Now I'm getting the following error: wbWriteToPage(): RetrieveAuthPage() Failure. Returning FALSE DavidBessler March 03, 2009, at 09:11 AM

Please check in WikiBox.ErrorLog and see if the error messages there help clarify any problems. Typically this is an authorization problem.

Can I not use wikibox with password-protected pages? DavidBessler March 03, 2009, at 01:46 PM

Yes, you can. But the ID you're using to submit changes has to have the appropriate authorizations. A user signed up through email rather than the form interface has no authorization (just as if he was not logged in at all). Whereas a user who signs up through the form interface gains any authorization that was present at the moment of signing up. Note paragraphs #2 and #3 under the "markup" section. Also quoting from the release notes:
Also if the user signs up using the form interface a snapshot of their current authorizations will be made and that will be used for any future read/edit operations from that email address.
Having said that, I've got to apologize for the documentation on this recipe. It needs a lot of work... Any improvements you would like to make are greatly appreciated.

Brilliant! Got it working. Now I have to work on my CRON script. This will revolutionize my journaling. I'll try to tidy up the documentation.DavidBessler

I keep getting this error with my cron script:

/home/content/a/b/c/abcusername/html/abcusername/wiki/mywikipostchecker: line 2: 1
: ambiguous redirect

(I've anonymized the path and filename) Any ideas? DavidBessler March 03, 2009, at 09:57 PM

Can you show me more of your cron script? What operating system are you running under. (The fact you mention cron suggests linux, but I just want to make sure.) Is your cron running on the same machine that is hosting your pmwiki installation or is it remote? Are you trying to use wget to load the page or are you going to try to call php directly on pmwiki.php with the appropriate setup? I've used wget successfully in different contexts but I've never tried the latter, although it should work fine (and be more efficient) once you figure out the ins and outs. The wget can be as simple as the word wget followed by a space followed by whatever URL you put in your address bar to access the page with the markup... But whatever wget uses will need to start with http:// or whatever...

For some reason, trying to cron the script directly yields a "file not found" error which I couldn't get past. I used the script/wget method with just:

wget "http://wiki.xxxxxxxx.com/pmwiki.php?n=WikiBox.Check"

and that is working. So now, it looks like I have the whole thing set up. Thanks so much for your help. DavidBessler March 04, 2009, at 02:32 AM

Glad it worked out in the end and hope it continues to do well by you. FYI cron has a very minimalistic environment when it runs scripts. I.e., you may not have the appropriate $PATH and you may not even be running bash -- you may be running some slimmed down shell. If you're interested in chasing it down let me know which file was not found and we can follow up. If you're pleased with the way it's working now then I'm happy too.
PS If you do decide to use this on an ongoing basis could you be sure to "sign" the WikiBox-Users page? (It's still not fully implemented but it looks like that is the most likely way recipes are going to be rated in the future...) Thanks!

  • How can I specify a remote SMTP host (with appropriate login info for it) instead of relying on a local transport? tamouse June 13, 2011, at 08:15 PM
It's been some time since I worked with this recipe, so the details are kind of fuzzy, but take a look at WikiMail configuration and you'll see setup for $WikiMailSMTP. If that doesn't work let me know and I'll look into it in more detail.
Thanks, I will look into it.

I must have messed up the config somehow. The mails being sent to the user or the moderator for action are being sent with the From: and Reply-to: set to _www@portfolio.paladin.local, which my local web server on my mac. Shouldn't this be set to the mailbox WikiBox.Check looks at instead?

Here's my config.php section:

    ## Adding stuff for wikibox - to allow addition of wiki pages by email
    ## http://www.pmwiki.org/wiki/Cookbook/WikiBox
    include_once("$FarmD/cookbook/toolbox.php");
    include_once("$FarmD/cookbook/SecLayer.php");
    include_once("$FarmD/cookbook/wikibox.php");
    include_once("$FarmD/cookbook/wikimail.php");
    $wbModerator = 'tamara@localhost';  // replace this with the email address of the moderator
                                       // you can also make it an array of addresses if more than 1
    # Normally this call to wmMkProfilePOP3() would be on a single line
    wmMkProfilePOP3('wikibox', //name of the profile - must be wikibox unless you change $wbPOP3Profile
       'localhost', // host where WikiBox will pick up mail
       'testwiki',        // username WikiBox will use to pick up mail
       ------);            // password WikiBox will use to pick up mail

My SiteAdmin.WikiBoxEmailAuth has in it:

 tamara@locahost:::1:0:--------::::::

(I'm not at all clear what the password field is for...) Nevermind, I figured it out. It goes in the message body of any pages to want to upload. tamouse June 14, 2011, at 12:49 AM

tamouse June 14, 2011, at 12:47 AM


User notes +4: If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.