The Message module provides:
  • Messaging within the database
  • Outbound email processing (SMTP integration)
  • Inheritance-based inboxes
  • Templates (canned messages)
  • Inbound email processing (POP3)

Templates: Canned Messages

Message Templates allow you to create "canned" or "mail merged" messages.  For example:

  • The Subject and Body may use "mail merge" fields by using curly braces around a field name (e.g. {LastName}
  • The fields available are determined by the object the message applies to (in this case, an Organization)
    • You can see a list of available fields by clicking on the ... icon to the right of the subject line

You may also pre-determine the To, Cc and Bcc recipients:

In the example to the right, we have three examples of recipients:
  1. sales@quandis.com is a 'hard coded' recipient; a copy of this message will always go to sales@quandis.com
  2. //Email is similar to the curly braces; it leverages any field that is part of the object the message applies to
  3. Contact/ListWhere runs a query to fetch all contacts for the organization the message applies to, and includes each one as a message recipient

Inbound Email Processing

QBO 3 sites can be configured to monitor email accounts, and import emails sent to these accounts as messages and attachments. Components include:
  • Web.config: links to MailInbound.config
  • MailInbound.config: identifies email accounts to monitor, and defines how to deal with emails found in these accounts
  • Message.config: contains one or more statements which are used to bind an email-based Message to an Object/ID based on the email subject
  • qbo.Message.Rebex: implements the Rebex POP3 provider to handle processing of emails over using POP3 
  • MessageObject.Receive: a method that iterates through each configured email account, and calls the underlying code to process the email inbox
Configuration of web.config

The web.config file needs to reference the MailInbound.config file, typically like this:

<sectionGroup name="qbo" type="System.Configuration.ConfigurationSectionGroup, ... >
<section name="MailInbound" type="qbo.Message.Configuration.MailInboundConfiguration, qbo.Message"/>
<MailInbound configSource="config\MailInbound.config"/>

Configuration of Message.config Statements

The key to effective email processing is figuring out what object to attach the Messages or Attachments to. This is done by leveraging the QBO 3 Smart Search technology. Typically, a Smart Search is performed based on the email subject line, and the highest weighted match is chosen as the Object/ID for the message. If no match is found, the Message can be attached to a "default" Object.

Assume a client named Acme Loan Servicing uses is loan-centric QBO installation (that is, most users spend their day working from Loan.ashx/Summary). They may set up an email address loans@acme.org, and provide Quandis with the credentials to access that email account. The standard Message statement "BindBySubject" can be used to bind an email to a Loan by scanning the subject line for either a Loan number or a Property Address. See the standard BindBySubject statement in Message.config in source control.

If Acme starts doing a lot of title work (that is, some of their users start working from Title.ashx/Summary instead of Loan.ashx/Summary), they have two options to determine whether messages get routed to a Loan vs. a Title:
  1. They can extend the BindBySubject statement to Smart Search on Title rows as well as Loan rows, or
  2. They can create another email account (titles@amce.org), and configure that account to use a different statement (BindTitleBySubject)
The later method is preferred, as it is easier to resolve conflicts between matching identifiers.

Configuration of MailInbound.config

The MailInbound.config defines each email account to be monitored.

<?xml version="1.0"?>
<Account Name="Loans" MessageStatement="BindBySubject" Host="pop.gmail.com" Port="995" Account="loans@acme.org" Password="myLoanPassword" Type="qbo.Message.Rebex.Pop, qbo.Message.Rebex"/>
<Account Name="Titles" MessageStatement="BindTitleBySubject" Host="pop.gmail.com" Port="995" Account="titles@acme.org" Password="myTitlePassword" Type="qbo.Message.Rebex.Pop, qbo.Message.Rebex" />

Specific properties of an Account within MailInbound.config include:
  • Name: a unique name representing the account
  • Type: system type of the class that will process the account (e.g. qbo.Message.Rebex.Pop(
  • Host: host name of the email server (e.g. pop.gmail.com)
  • Account: email account to access (e.g. loan@acme.org)
  • Password: email account password
  • Timeout: (optional) timeout setting when connecting to the email server
  • Port: port to use when access email server 
  • EnableSsl: (optional, defaults to true) whether to use SSL when communicating with the email server
  • Permission: (optional) if set, the From email address must be an active user, and have permissions to this function (e.g. MessageInsert)
  • BindAttachmentsToMessage: (optional, defaults to false) if true, any attachments will be bound to the Message; otherwise to the Message's parent
  • MessageStatement: (optional, defaults to BindBySubject) determines the Statement in the Message.config file to use to determine message binding

Inbox: Individuals and Groups

Use case: Require a Read Receipt from a User

One can create a Message Recipient, with the ReadRequired bit set to true. This will cause a message to appear in the individual's inbox, with a visual indication that they must read the message. When the user views the message, the system will make the MessageRecipient.ReadDate, providing an audit trail proving the user read the message.

Use case: Require a Read Receipt from a Department

QBO systems are used to coordinate work across multiple organizations. Frequently, a client requires that someone within a vendor's organization acknowledges receipt of a message, but they do not care who. In this case, a Message Recipient targeting a Group can be created, and any member of the group can mark the message as read. After one member of the group acknowledges the message as read, it is considered read by the entire group; other users reading it makes no technical difference.
  • target a whole company: RecipeintObject/ID = 'Organization'/{OrganizationID} (e.g. Dewey Cheetum and Howe lawfirm)
  • target a department: RecipientObject/ID = 'Collection'/{CollectionID} (e.g. Dewey Cheetum and Howe Foreclosure Department)
  • target any broker within a brokerage office: RecipientObject/ID = 'Broker'/{BrokerID} (e.g. Coldwell Realtors - Laguna Beach, CA)
Use case: Require a Read Receipt from all members of a System Role.

In some cases, one wishes every single member of a group to explicitly acknowledge receipt of a message. In this case, one would add a MessageRecipient row for each user that is a member of the group. For example, one may require all Brokers to acknowledge a change to terms of service. If there are 12000 brokers in the system, this implies the creation of 12000 MessageRecipient rows, each tracking it's own Read date, rather than a single MessageRecipient row targeting the Broker role.