E-Mail: Incoming E-Mail
Incoming E-Mail in OpenACS works with the latest version of acs-mail-lite in a general fashion using callbacks.
The original version of this documentation is found via archive.org at: http://www.cognovis.de/developer/en/incoming_email
We will take a look on what needs to be done to get incoming e-mail working and then continue on to see how packages can benefit.
Project notes: ACS Mail Lite sends via SMTP which permits the use of an external server to handle email. For scalability, consider expanding the incoming E-mail paradigm to likewise use Tcllib's imap4 or NaviServer's nsimap so that most all email can be handled on separate servers.
Install incoming E-Mail
First, one must have an understanding of postfix basics. See http://www.postfix.org/BASIC_CONFIGURATION_README.html.
These instructions use the following example values:
- hostname: www.yourserver.com
- oacs user: service0
- OS: Linux
- email user: service0
- email's home dir: /home/service0
- email user's mail dir: /home/service0/mail
Important: The email user service0 does not have a ".forward" file. This user is only used for running the OpenACS website. Follow careful use of email rules by following strict guidelines to avoid email looping back unchecked.
For postfix, the email user and oacs user do not have to be the same. Furthermore, postfix makes distinctions between virtual users and user aliases. Future versions of this documentation should use examples with different names to help distinguish between standard configuration examples and the requirements of ACS Mail Lite package.
Postfix configuration parameters:
myhostname=www.yourserver.com myorigin=$myhostname inet_interfaces=$myhostname, localhost mynetworks_style=host virtual_alias_domains = www.yourserver.com virtual_maps=regexp:/etc/postfix/virtual home_mailbox=mail/
Here is the sequence to follow if installing email service on system for first time. If your system already has email service, adapt these steps accordingly:
- Install postfix
- Install smtp (for postfix)
- Install metamail (for acs-mail-lite)
- Edit /etc/postfix/main.cf
- Edit /etc/postfix/virtual Add a regular expression to filter relevant incoming emails for processing by OpenACS.
@www.yourserver.com service0
- Edit /etc/postfix/master.cf - uncomment this line so postfix listens to emails from internet
smtp inet n - n - - smtpd
- Create a mail directory as service0
mkdir /home/service0/mail
- Configure ACS Mail Lite parameters
BounceDomain: www.yourserver.com
BounceMailDir: /home/service0/mail
EnvelopePrefix: bounce
The EnvelopePrefix is for bounce e-mails only.
NOTE: Parameters should be renamed:
BounceDomain to IncomingDomain
BounceMailDir to IncomingMaildir
EnvelopePrefix to BouncePrefix
..to reflect that acs-mail-lite is capable of dealing with other types of incoming e-mail.
Furthermore, setting IncomingMaildir parameter clarifies that incoming email handling is setup. This is useful for other packages to determine if they can rely on incoming e-mail working (e.g. to set the reply-to email to an e-mail address which actually works through a callback if the IncomingMaildir parameter is enabled). - Configure Notifications parameters
EmailReplyAddressPrefix: notification
Configure other packages likewise
EmailQmailQueueScanP: 0
We want acs-mail-lite incoming handle the Email Scanning, not each package separately.
- Invoke postmap in OS shell to recompile virtual db:
postmap /etc/postfix/virtual
- Restart Postfix.
/etc/init.d/postfix restart
- Restart OpenACS
Processing incoming e-mail
A sweeper procedure like acs_mail_lite::load_mails should:
- scan the e-mails which are in the IncomingMaildir directory on a regular basis.
- check if any email came from an auto mailer.
- Parse new ones, and
- process them by firing off callbacks.
Vinod has made a check for auto mailers by using procmail as follows. Maybe we could get this dragged into Tcl code (using regexp or a Procmail recipe parser) instead, thereby removing the need for setting up procmail in the first place.
:0 w * ^subject:.*Out of Office AutoReply /dev/null :0 w * ^subject:.*Out of Office /dev/null :0 w * ^subject:.*out of the office /dev/null :0 w * ^subject:.*NDN /dev/null :0 w * ^subject:.*[QuickML] Error: /dev/null :0 w * ^subject:.*autoreply /dev/null :0 w * ^from.*mailer.*daemon /dev/null
To make things granular a separate parsing procedure should deal with loading the e-mail into the Tcl interpreter and setting variables in an array for further processing.
ad_proc parse_email { -file:required -array:required } { ... }
An email is split into several parts: headers, bodies and files.
The headers consists of a list with header names as keys and their corresponding values. All keys are lower case.
The bodies consists of a list with two elements: content-type and content.
The files consists of a list with three elements: content-type, filename and content.
An array with all the above data is upvarred to the caller environment.
Processing an email should result in an array like this:
HEADERS
- message_id
- subject
- from
- to
- date
- received
- references
- in-reply-to
- return-path
- .....
X-Headers:
- X-Mozilla-Status
- X-Virus Scanned
- .....
We do not know which headers are going to be available in the e-mail. We set all headers found in the array. The callback implementation then checks if a certain header is present or not.
#get all available headers set keys [mime::getheader $mime -names] set headers [list] # create both the headers array and all headers directly for the email array foreach header $keys { set value [mime::getheader $mime $header] set email([string tolower $header]) $value lappend headers [list $header $value] } set email(headers) $headers
Bodies
An e-mail usually consists of one or more bodies. With the advent of complex_send, OpenACS supports sending of multi-part e-mails which are needed if you want to send out and e-mail in text/html and text/plain (for old mail readers).
switch [mime::getproperty $part content] { "text/plain" { lappend bodies [list "text/plain" [mime::getbody $part]] } "text/html" { lappend bodies [list "text/html" [mime::getbody $part]] } }
Files
OpenACS supports tcllib mime functions. Getting incoming files to work is a matter of looking for a part where there exists a "Content-disposition" part. All these parts are file parts. Together with scanning for email bodies, code looks something like this:
set bodies [list] set files [list] #now extract all parts (bodies/files) and fill the email array foreach part $all_parts { # Attachments have a "Content-disposition" part # Therefore we filter out if it is an attachment here if {[catch {mime::getheader $part Content-disposition}]} { switch [mime::getproperty $part content] { "text/plain" { lappend bodies [list "text/plain" [mime::getbody $part]] } "text/html" { lappend bodies [list "text/html" [mime::getbody $part]] } } } else { set encoding [mime::getproperty $part encoding] set body [mime::getbody $part -decode] set content $body set params [mime::getproperty $part params] if {[lindex $params 0] == "name"} { set filename [lindex $params 1] } else { set filename "" } # Determine the content_type set content_type [mime::getproperty $part content] if {$content_type eq "application/octet-stream"} { set content_type [ns_guesstype $filename] } lappend files [list $content_type $encoding $filename $content] } } set email(bodies) $bodies set email(files) $files
Note that the files ie attachments are actually stored in the /tmp directory from where they can be processed further. It is up to the callback to decide if to import the file into OpenACS or not. Once all callbacks have been fired files in /tmp will have to be deleted again though.
Firing off callbacks
Now that we have the e-mail parsed and have an array with all the information, we can fire off the callbacks. The firing should happen in two stages.
The first stage is where we support a syntax like "object_id@yoursite.com".
Second, incoming e-mail could look up the object_type, and then call the callback implementation specific to this object_type. If object_type = 'content_item', use content_type instead.
ad_proc -public -callback acs_mail_lite::incoming_object_email { -array:required -object_id:required } { }
callback acs_mail_lite::incoming_object_email -impl $object_type -array email -object_id $object_id
ad_proc -public -callback acs_mail_lite::incoming_object_email -impl user { -array:required -object_id:required } { Implementation of mail through support for incoming emails } { # get a reference to the email array upvar $array email # make the bodies an array template::util::list_of_lists_to_array $email(bodies) email_body if {[exists_and_not_null email_body(text/html)]} { set body $email_body(text/html) } else { set body $email_body(text/plain) } set reply_to_addr "[party::get_by_email $email(from)]@[ad_url]" acs_mail_lite::complex_send \ -from_addr $from_addr \ -reply_to $reply_to_addr \ -to_addr $to_addr \ -subject $email(subject) \ -body $body \ -single_email \ -send_immediately }
Object id based implementations are useful for automatically generating "reply-to" addresses. With ProjectManager and Contacts object_id is also handy, because Project / TaskID is prominently placed on the website. If you are working on a task and you get an e-mail by your client that is related to the task, just forward the email to "$task_id@server.com" and it will be stored along with the task. Highly useful :).
Obviously you could have implementations for:
-
forums_forum_id: Start a new topic
-
forums_message_id: Reply to an existing topic
-
group_id: Send an e-mail to all group members
-
pm_project_id: add a comment to a project
-
pm_task_id: add a comment to a task and store the files in the projects folder (done)
Once the e-mail is dealt with in an object oriented approach we are either done with the message (an object_id was found in the to address) or we need to process it further.
ad_proc -public -callback acs_mail_lite::incoming_email { -array:required -package_id } { }
array set email {} parse_email -file $msg -array email set email(to) [parse_email_address -email $email(to)] set email(from) [parse_email_address -email $email(from)] # We execute all callbacks now callback acs_mail_lite::incoming_email -array email
For this a general callback should exist which can deal with every leftover e-mail and each implementation will check if it wants to deal with this e-mail. How is this check going to happen? As an example, a package could have a prefix, as is the case with bounce e-mails as handled in acs_mail_lite::parse_bounce_address (see below):
ad_proc -public -callback acs_mail_lite::incoming_email -impl acs-mail-lite { -array:required -package_id:required } { @param array An array with all headers, files and bodies. To access the array you need to use upvar. @param package_id The package instance that registered the prefix @return nothing @error } { upvar $array email set to [acs_mail_lite::parse_email_address -email $email(to)] ns_log Debug "acs_mail_lite::incoming_email -impl acs-mail-lite called. Recepient $to" util_unlist [acs_mail_lite::parse_bounce_address -bounce_address $to] user_id package_id signature # If no user_id found or signature invalid, ignore message # Here we decide not to deal with the message anymore if {[empty_string_p $user_id]} { if {[empty_string_p $user_id]} { ns_log Debug "acs_mail_lite::incoming_email impl acs-mail-lite: No equivalent user found for $to" } else { ns_log Debug "acs_mail_lite::incoming_email impl acs-mail-lite: Invalid mail signature $signature" } } else { ns_log Debug "acs_mail_lite::incoming_email impl acs-mail-lite: Bounce checking $to, $user_id" if { ![acs_mail_lite::bouncing_user_p -user_id $user_id] } { ns_log Debug "acs_mail_lite::incoming_email impl acs-mail-lite: Bouncing email from user $user_id" # record the bounce in the database db_dml record_bounce {} if {![db_resultrows]} { db_dml insert_bounce {} } } } }
Alternatively we could just check the whole to address for other things, e.g. if the to address belongs to a group (party)
ad_proc -public -callback acs_mail_lite::incoming_email -impl contacts_group_mail { -array:required {-package_id ""} } { Implementation of group support for incoming emails If the to address matches an address stored with a group then send out the email to all group members @author Malte Sussdorff (malte.sussdorff@cognovis.de) @creation-date 2005-12-18 @param array An array with all headers, files and bodies. To access the array you need to use upvar. @return nothing @error } { # get a reference to the email array upvar $array email # Now run the simplest mailing list of all set to_party_id [party::get_by_email -email $email(to)] if {[db_string group_p "select 1 from groups where group_id = :to_party_id" -default 0]} { # make the bodies an array template::util::list_of_lists_to_array $email(bodies) email_body if {[exists_and_not_null email_body(text/html)]} { set body $email_body(text/html) } else { set body $email_body(text/plain) } acs_mail_lite::complex_send \ -from_addr [lindex $email(from) 0] \ -to_party_ids [group::get_members -group_id $to_party_id] \ -subject $email(subject) \ -body $body \ -single_email \ -send_immediately } }
Or check if the to address follows a certain format.
ad_proc -public -callback acs_mail_lite::incoming_email -impl contacts_mail_through { -array:required {-package_id ""} } { Implementation of mail through support for incoming emails You can send an e-amil through the system by sending it to user#target.com@yoursite.com The email will be send from your system and if mail tracking is installed the e-mail will be tracked. This allows you to go in direct communication with a customer using you standard e-mail program instead of having to go to the website. @author Malte Sussdorff (malte.sussdorff@cognovis.de) @creation-date 2005-12-18 @param array An array with all headers, files and bodies. To access the array you need to use upvar. @return nothing @error } { # get a reference to the email array upvar $array email # Take a look if the email contains an email with a "#" set pot_email [lindex [split $email(to) "@"] 0] if {[string last "#" $pot_email] > -1} { .... } }
Alternatives to this are:
- ${component_name}-bugs@openacs.org (where component_name could be openacs or dotlrn or contacts or whatever), to store a new bug in bug-tracker
- username@openacs.org (to do mail-through using the user name, which allows you to hide the actual e-mail of the user whom you are contacting).
Cleanup
Once all callbacks have been fired off, e-mails need to be deleted from the Maildir directory and files which have been extracted need to be deleted as well from the /tmp directory.
in last 30 minutes
OpenACS.org
- HOME
- News
- OpenACS Projects
- Activity Graph
- Admin Package RFC
- Bugtracker Cleanup Project
- Collaboration Graph
- Community Metrics in OpenACS
- Debian/Ubuntu installer developing
- Documentation Project
- Documentation Project Discussion
- Documentation Project Plan (Approach 4)
- {done} Change Log from OpenACS 5.4.2 to OpenACS 5.4.3
- {done} OpenACS 5.3.x releases
- {done} Release Notes OpenACS 5.4.3
- Dynamic Object Types and Attributes
- Ecommerce G2
- E-Mail: Event Handling
- E-Mail: Incoming E-Mail
- E-Mail: Outgoing E-Mail
- Forums Project
- GETable resources, that should be POSTable resources
- Interface / CSS Coding Guidelines
- Logo
- .LRN
- Mentorship Program
- Migration from CVS to GIT
- Official Test Servers
- OpenACS 5.10.0 Change Summary
- OpenACS 5.10.1 Change Summary
- OpenACS 5.9 HTML validity fixes
- OpenACS/.LRN for Debian
- OpenACS Packaging for Debian and Ubuntu
- OpenACS Release Status
- OpenACS TODO List
- Package Object Types
- Package Testing Process
- Prerequisites and Procedures for Migrating to Subversion from CVS
- Site Nodes Proposal (Draft)
- Site Wide File Upload
- Site Wide Image Upload Widget
- (Sketch for) OpenACS Home
- Theme Manager
- Theming Project
- Translation server for OpenACS packages
- User interface mockups
- Website_Redesign
- XoWiki Design Ideas
- YUI Project
- Marketing
- Our Website
- Packages
- Available OpenACS Packages
- Core Packages
- ACS Admin
- ACS API Browser
- ACS Authentication
- ACS Automated Testing
- ACS Bootstrap Installer
- ACS Content Repository
- ACS Core Docs
- ACS Default Theme
- ACS Developer Support
- ACS Kernel
- ACS Lang
- ACS Mail Lite
- ACS Messaging
- ACS Reference Data
- ACS Service Contract
- ACS Subsite
- ACS Tcl
- ACS Templating
- ACS Translations
- Intermedia Driver
- Notifications
- Reference Data - Country
- Reference Data - Language
- Reference Data - Timezone
- Search
- Tsearch2 Driver
- Non-Core Packages
- ACS Date Time
- ACS Events
- ACS Interface
- ACS Object Management
- Address Book
- Ad Server
- Ajax Filestore UI
- Ajax Helper
- Ajax Photoalbum UI
- Anonymous Evaluation
- Assessment
- Attachments
- Attendance
- Attribute Management System
- Auth CAS
- Authentication Server
- Auth HTTP
- Authorize.net Gateway
- Beehive
- Bookmarks
- Bookshelf
- Boomerang Plugin
- B Responsive Theme
- Bug tracker
- Bulk mail
- Calendar
- Calendar Includelet
- Cards
- Categories
- Chat
- Chat Includelet
- Clickthrough
- Clipboard
- CMS
- CMS News Demo
- Connections
- Contacts
- Contacts Lite
- Content Includelet
- Cookie Consent Widget
- Cronjob
- Curriculum
- Curriculum Central
- Curriculum Tracker
- Datamanager
- dbm
- Diagram
- Directory
- Download
- Dynamic Object Type
- E-Commerce
- Ecommerce Serial Number Tracking
- Edit This Page
- EduWiki
- Email Handler
- Evaluation
- Expense
- Expense Tracking
- EZIC Gateway
- Facebook API
- FAQ
- Feed parser
- File Manager
- File storage
- File Storage Includelet
- Forums
- Forums Includelet
- GateKeeper
- General comments
- Glossar
- Glossary
- Image Magick
- IMS Enterprise
- Imsld
- Invoices
- Jabber
- Lab Report
- Lab Report Central
- LAMS Integration
- LAMS Integration Configuration
- Latest
- Layout Managed Subsite
- Layout Manager
- LDAP Authentication Driver
- Learning Content
- Logger
- LORS management Includelet
- Mail Tracking
- MMplayer
- Monitoring
- New portal
- News
- News aggregator
- News Includelet
- Notes
- OCT Election
- openacs-bootstrap3-theme
- Organization
- Outdated Library functions
- Package Builder
- Page
- Pages
- PAM Authentication Driver
- Payment Gateway
- Permissions Administrator
- Photo album
- Planner
- Poll
- Postal Address
- Post Card
- Press
- Profile provider
- Project Manager
- Q-Forms
- Quota
- Q-Wiki
- Ratings
- Recruiting
- Redirect
- Reference Data - Currency
- Reference Data - ITU Code
- Reference Data - UNSPSC code
- Reference Data - US County
- Reference Data - US State
- Reference Data - US Zipcode
- Related Items
- Richtext CKEditor 4
- Richtext CKEditor 5
- Richtext TinyMCE
- Richtext Xinha
- Robot Detection
- RSS support
- S5
- Sample Gateway
- Schema Browser
- Scholarship Fund
- Scorm Core
- Scorm Importer
- Scorm Player
- Scorm Simple LMS
- Selva theme
- Shipping Service Contract
- Simple Survey
- Simulation
- Site-wide Search
- Skin
- SOAP db
- SOAP Gateway
- Spreadsheet
- Static Pages
- Survey
- Survey Library
- Survey Reports
- T Account
- Tasks
- Tcl SOAP
- Telecom Information
- Trackback
- User preferences
- User profile
- Value-based Shipping
- Version Control
- Views
- WebDAV Support
- Weblogger
- Webmail System
- Wikipedia
- Wimpypoint slim
- Workflow
- XCMS User Interface
- XML RPC
- XO Learning Performance
- xolirc
- xooauth
- XOTcl Core
- XOTcl Request Monitor
- xowf plugin for Monaco code editor
- xowf (XoWiki Workflow)
- XoWiki
- XoWiki Includelet
- ecommerce-g2
- Accounts Desk
- Accounts Finance
- Accounts Payables
- Accounts Payroll
- Accounts Receivables
- Bulk Upload
- CL Custom Commerce
- Customer Service
- E-commerce 2
- Fabrication
- Field Service
- General Ledger
- Human Resources
- Inventory Control
- Manufacturing Design
- Online Catalog
- Production
- Reference Data - GIFI
- Ship-Track
- Vendors-Suppliers
- DotLrn
- Anon Eval Applet
- Anon Eval Portlet
- Application track
- Application track Applet
- Application track portlet
- Assessment Applet
- Assessment portlet
- Attendance Applet
- Beehive Applet
- Beehive Portlet
- Bulk mail Applet
- Bulk mail Portlet
- Calendar Applet
- Calendar portlet
- Cards applet
- Cards portlet
- Chat Applet
- Chat Portlet
- Contacts Applet
- Contacts Portlet
- Content Applet
- Content Portlet
- Courses
- Curriculum Applet
- Curriculum Portlet
- Datamanager Portlet
- dotLRN
- dotLRN Administration
- dotLRN applet
- dotLRN Bootstrap 3 Theme
- dotLRN Course Catalog
- dotLRN Datamanager Applet
- dotLRN - Ecommerce
- dotLRN portlet
- dotLRN Roadmap
- Edit-this-page Applet
- Edit-this-page Portlet
- EduWiki Applet
- EduWiki Portlet
- Evaluation applet
- Evaluation portlet
- Expense-tracking Applet
- FAQ Applet
- FAQ Portlet
- File Storage Applet
- File Storage Portlet
- Forums Applet
- Forums Portlet
- Glossar Applet
- Glossar Portlet
- Homework Applet
- IMS-LD Applet
- IMS LD Portlet
- Invoices Applet
- Invoices Portlet
- Jabber Applet
- Jabber Portlet
- LAMS Integration Applet
- LAMS Integration Portlet
- Latest Applet
- Latest Portlet
- Learning Content Applet
- Learning Content Portlet
- LORS central
- LORS - Learning Objects Repository Service
- LORS management
- LORS management Applet
- LORS management Portlet
- Messages Applet
- Messages Portlet
- MMplayer Applet
- MMplayer Portlet
- News Aggregator Applet
- News Aggregator Portlet
- News Applet
- News Portlet
- Photo Album Applet
- Photo Album Portlet
- Private-Message
- Project-manager Applet
- Project Manager Portlet
- Quota Applet
- Quota Portlet
- Random-photo Applet
- Random-photo Portlet
- Recruiting Applet
- Recruiting Portlet
- Research Applet
- Research Portlet
- Static Applet
- Static Portlet
- Survey Applet
- Survey Portlet
- Syllabus Applet
- Tasks Applet
- Tasks Portlet
- Theme Zen
- User Tracking
- User Tracking Applet
- User Tracking Portlet
- Weblogger Applet
- Weblogger Portlet
- Wikipedia Applet
- Wikipedia Portlet
- Wimpypoint Slim Applet
- Wimpypoint Slim Portlet
- XoWiki Applet
- XoWiki Portlet
- Contrib Packages
- Acknowledgement
- BCDS
- BCMS
- BCMS UI Base
- BCMS UI Wizard
- Classified Ads
- COP Base
- COP UI
- Events Management
- Form To Mail
- Irc Applet
- IRC Logger
- Mail Clickthrough
- mailing-lists
- PayFlowPro Gateway
- Personal Community
- Photobook
- Populate
- Research Papers
- Resource List
- Room Reservation
- Users Selection
- Vocabulary
- Deprecated Packages
- {deprecated} ACS Content
- {deprecated} ACS LDAP Authentication
- {deprecated} ACS Mail
- {deprecated} ACS Utility Services
- {deprecated} Bboard Portlet
- {deprecated} dotFOLIO
- {deprecated} dotFOLIO UI
- {deprecated} dotLRN BBoard Applet
- {deprecated} OpenFTS Driver
- {deprecated} Portal
- {deprecated} Sloan Bboard
- {deprecated} Spam System
- {deprecated} Webmail
- {deprecated} Wiki
- {deprecated} Workflow Service
- Community
- Getting admin-level help
- Getting help
- Goals / Ideas
- History of OpenACS
- Marketing Team
- Most Popular Pages
- OpenACS Translation server
- Events
- 2006 Fall Conference Interest in Attending
- 2006 Fall Conference Presentations
- 2006 Fall Conference Submissions and Program
- 2006 International Workshop on Community Based E-Learning Systems
- 2006 November 2nd (General Web Applications Focus - OpenACS)
- 2006 November 3rd and November 4th (Training and Hacking Days)
- 2006 OpenACS/.LRN Fall Conference
- 2006 Session 1: Towards full Accessibility in LMS
- 2007 Project Ideas for Google Summer of Code
- OpenACS conferences
- OCT
- F. A. Q.
- .LRN
- 2006 Fall Conference Submissions and Program
- Content development tools options
- Documentation and help pages for individual .LRN installations
- Educational Wiki (Eduwiki) Tool
- How to contribute code that passes accessibility tests
- Learning Content Tool
- .LRN
- .LRN Accessibility
- .LRN Core Team (DRAFT)
- .LRN Educational standards support
- .LRN Get Involved!
- .LRN Governance
- .LRN Installation
- .LRN Installation (up to .LRN 2.5.0)
- .LRN Leadership Team 2008
- .LRN Meetings
- .LRN Motions (DRAFT)
- Modelling Learners Preferences
- Plataforma Elearning
- SCORM support
- Simple Content Creator / Editor
- Time/Topics Planner for dotLRN Courses
- Consortium
- Releases
- .LRN 2.2 bugs
- .LRN 2.2 Release Management
- .LRN 2.2 to .LRN 2.3.0 Change Log
- .LRN 2.3.0 to .LRN 2.3.1 Change Log
- .LRN 2.3.1 Release Notes
- .LRN 2.3.1 to .LRN 2.4 Change Log
- .LRN 2.3 Release Management
- .LRN 2.4.0 to .LRN 2.4.1 Change Log
- .LRN 2.4.1 Release Notes
- .LRN 2.4 Release Management
- .LRN 2.4 Release Notes
- .LRN 2.5 Release Management
- Zen Project
- Coding Standards
- ADP Files
- Ajax and Accessibility
- Code Formatting
- Coding Standards - Index
- Commit Messages
- Emacs as an OpenACS IDE
- How to contribute code that passes accessibility tests
- Logging Conventions
- .LRN Zen Project: Standards
- Naming Conventions
- Security Guidelines
- SQL - XQL
- Tcl pages
- Tcl Procs
- template::head::*
- Vi as an OpenACS IDE
- WCAG 1.0 Checkpoints
- Web Forms
- Web Lists / Tables
- External Resources
- Cookbook
- Accessing LTI services from OpenACS
- Add extra headers
- Cookbook
- Creating adp box tags for consistent html/css
- Double Click Handling
- E-Mail: Event Handling
- E-Mail: Incoming E-Mail
- E-Mail: Outgoing E-Mail
- F. A. Q.
- Fresh install of OpenACS 5.10 on Oracle 19c
- Handling out of memory on "exec" calls
- Host Node Map
- How to configure a Network Place under Windows XP to access file-storage via WebDAV
- How to handle "connection already closed" errors
- How to manage/upgrade CKEditor versions
- How to tune cache sizes
- Interfacing with MS Teams and related services (Microsoft Graph)
- Managing Versions of External JavaScript Libraries
- Modifying the look of an installation
- NaviServer and OpenACS with Docker
- New Interface for Calling Database functions
- OpenACS Performance Tuning
- Passing values up from an include
- Permissions explored, a practical way exists
- Refactoring Recipes
- Running OpenACS behind a proxy
- Security: Content Security Policy (CSP)
- Security: Cross Site Request Forgery (CSRF)
- Server-sent events
- Setup with docker-s6
- SQL: How to log (slow) queries in the system log
- Streaming HTML
- Using OpenACS with External Identity Providers
- Using Pound as a reverse Proxy
- When to use URLencode
- XoWiki: How to save files directly in the wiki
- XoWiki: List of the available includelets
- Resources
- Accessibility
- Testing Pages
- category test
- Commit graph
- Commits
- Comparison of the CTRL Surveys Package vs. the OACS Assessment Package
- fullpage
- just playing around
- name with space
- OpenACS Object Types
- Pastebin for irc
- preview.png
- QUOTA
- Recently Changed Pages
- toc-test-page
- Wikipedia
- XoWiki Slides from the Vienna OpenACS conference
- Directory - Who's Who
- Documentation
- Collaboration Graph
- Documentation Credits
- Documentation History
- Documentation Introduction
- Documentation Process test-doc (Approach 3)
- Documentation Project Discussion
- Documentation Project Plan (Approach 4)
- for administrators
- for administrators - Table of Contents
- for beginning developers
- for developers
- for developers - Table of Contents
- for everyone
- for everyone - Table of Contents
- Most Popular Pages
- OpenACS Handbook
- Try Openacs
- WikiDoc Project Notice
- Package Documentation
- Aliases at CVS
- Available OpenACS Packages
- Packages available in the oacs-5-10 channel
- Packages available in the oacs-5-9 channel
- Documentation Non-Core Packages
- Marketing Documentation
- Tutorials
- Developer Tutorial - Req.
- for beginning developers
- Introduction to OpenACS
- Next Steps After Installation, Debian Specific
- OpenACS/dotLRN windows installer how to
- Theming in OpenACS
- Tutorials for Designers
- Tutorials for Users
- Tutorials for Administrators
- Tutorials for Programmers
- Add extra headers
- Automated Installs - Using install.xml
- Body Onload javascript event
- Emacs as an OpenACS IDE
- listbuilder tutorial
- OpenACS 5.1.4 / PG 7.3.6 => 5.2.3/8.0.7 Upgrade Path for acs-core
- OpenACS mode for Emacs
- Vi as an OpenACS IDE
- Webinar - Part 1 - Basics
- Webinar - Part 2 - Site Map Administration
- Webinar - Part 3 - Packages and ad_form
- Webinar - Part 4 - Survey
- Tutorials - The N00B Journey
- Core Documentation
- Subsystems Documentation
- Administrators - Req.
- AOLserver
- AOLserver administration
- Available OpenACS Packages
- Boost your application performance to serve large files!
- Conditional CREATE Index for Postgresql and Oracle
- Deployment feedback channel
- Developer - Requirements
- Developer Tutorial - Req.
- Emacs as an OpenACS IDE
- End-users - Requirements
- for administrators
- for administrators - Table of Contents
- for beginning developers
- for developers
- for developers - Table of Contents
- for everyone
- for everyone - Table of Contents
- Get the OpenACS Source Code
- Getting admin-level help
- hstore
- Install a *nix-based operating system (OS)
- Install AOLserver
- Install AOLserver 4.5
- Installation - Req.
- Installing OpenACS
- Installing OpenACS on Arch Linux
- Installing OpenACS on debian
- Installing OpenACS on FreeBSD
- Installing OpenACS on FreeBSD (quick)
- Installing OpenACS on FreeBSD with ports
- Installing OpenACS on Mac OS X
- Installing OpenACS on Redhat
- Installing OpenACS on RPM-based systems
- Installing OpenACS on Solaris
- Installing OpenACS on SuSE
- Installing OpenACS on win2k
- Installing OpenACS on Windows
- Install OpenACS distribution
- Install OpenACS on debian unstable / Ubuntu 7.10
- Install OpenACS on Linux
- Install OpenACS on Mac OS X 10.5 / 10.6 (Snow Leopard) Using Macports
- Install OpenACS - prereqs
- Install OpenACS with NaviServer from Scratch
- Install Oracle
- Install Postgresql
- Install Tcl
- Mail Transport Agents
- Monitoring Naviserver
- Nagios Monitoring
- NaviServer
- Next Steps After Installation, Debian Specific
- *nix operating system
- OpenACS compatibility matrix
- OpenACS Debian Install quicksheet
- OpenACS/dotLRN windows installer how to
- OpenACS/dotLRN Windows Installer Instructions
- OpenACS/.LRN for Debian
- OpenACS/.LRN for Ubuntu
- OpenACS Monitoring
- OpenACS Performance Tuning
- OpenACS Reference Platform
- OpenACS subsystem
- OpenACS system
- Oracle
- Oracle Notes
- Postgres 8.1.x to 9.1
- PostgreSQL
- PostgreSQL Administration
- PostgreSQL's Tsearch2
- Securing your system
- Source control
- Tcl
- Tcl Thread Library
- tDOM
- tDOM with OpenACS
- Testing with Selenium
- Testing with TCLWebtest
- Upgrade between PostgreSQL versions
- Upgrade from PostgreSQL 9.6 to 13.1
- Upgrade to OpenACS 5.10
- Upgrade to OpenACS 5.8
- Upgrade to OpenACS 5.9
- Vi as an OpenACS IDE
- ::xo::db Object Relational Database Interface
- XOTcl