Revision as of 16:06, 20 August 2012 by Jwagner (talk | contribs) (Undo revision 51458 by Jwagner (talk))


note: A license is required to enable the Voice tab for Unified Communications. Additionally the tab is controlled by setting zimbraFeatureVoiceEnabled to TRUE at the COS or user level.

Voice Mail Tab

The voice mail tab provides a list view of a user’s voice mails. Depending on the provider implementation it may also consist of missed calls, answered calls and placed calls.

The Voice Mail tab is populated by making a call to SearchVoiceRequest. More details can be found in soap-voice.txt.

Click to Call

Providing click to call capability via a zimlet can be broken down into three areas.

Contact Card

Adding Click to Call icon to the contact card In order to add the click to call icon to the contact card you need to first register your zimlet as a subscriber:

 function(emailZimlet) {
MyClick2CallZimlet.prototype.onEmailHoverOver =
function(emailZimlet) {

You can then add an icon to the contact card and register a callback for implementing functionality by adding a EmailToolTipSlide:

MyClick2CallZimlet.prototype._addSlide =
function(emailZimlet) {
   //Do not show "Call" slide if unauthorized to use UC feature
   if (!appCtxt.getSettings()._hasVoiceFeature()) {
   var tthtml = this._getTooltipBGHtml(); //HTML
   var selectCallback =  new AjxCallback(this, this._handleSlideSelect);
  this._slide = new EmailToolTipSlide(tthtml, true, "Click2CallZimletIcon", selectCallback, "Click to call");

Finally, your zimlet needs to implement onPhoneClicked:

MyClick2CallZimlet.prototype.onPhoneClicked =
function(phone) {
   if (!this.myFromPhoneDlg) {
       this.myFromPhoneDlg = new MyClick2CallFromPhoneDlg(this.getShell(), this,
   this.MyFromPhoneDlg.toPhoneNumber = this.toPhoneNumber = phone;

Providing a click to call dialog

Now that you have your zimlet registered with the contact card, you’ll want to implement a dialog to display when the user clicks on your icon to make a call.

To create the dialog you can extend ZmDialog:

MyClick2CallFromPhoneDlg = function(shell, parent) {
this.zimlet = parent;
this.toPhoneNumber = "";
this._dialogView = new DwtComposite(appCtxt.getShell());
this._dialogView.setSize(300, 125);
DwtDialog.call(this, {
   parent: shell,
   className: "ZmClick2CallFromPhoneDlg",
   title: this.zimlet.getMessage("fromPhoneDlgTitle"),
   view: this._dialogView,
   standardButtons: [DwtDialog.NO_BUTTONS],
   mode: DwtBaseDialog.MODELESS
 this._buttonDesc = {};
this._isLoaded = false;
this.RE = new RegExp("\\+?\\b\\d([0-9\\(\\)\\.\\s\\-]){8,20}\\d\\b");
MyClick2CallFromPhoneDlg.prototype = new ZmDialog; 
MyClick2CallFromPhoneDlg.prototype.constructor = MyClick2CallFromPhoneDlg;

In order to use this dialog to make calls you’ll need to know the from & to. In cases like the contact card you’ll want to prefill the “to” number. You can do so with something like:

 var cardAttributes = this.emailZimlet && this.emailZimlet.contactCard && this.emailZimlet.contactCard.attribs;
if (!cardAttributes) return;
this.click2CallDlg.toPhoneNumber = this.zimlet.toPhoneNumber = cardAttributes.mobilePhone || cardAttributes.workPhone;

In order to get the “from” number(s) (e.g. show a drop down of the numbers available to the user), the request will be based on your UC provider. Here’s one example of issuing a GetVoiceInfoRequest to retrieve the phone numbers:

MyClick2CallFromPhoneDlg.prototype._getVoiceInfoAndShowDlg =
function() {
var soapDoc = AjxSoapDoc.create("GetVoiceInfoRequest", "urn:zimbraVoice");
var respCallback = new AjxCallback(this, this._handleResponseVoiceInfo);
var respErrorCallback = new AjxCallback(this, this._handleErrorResponseVoiceInfo);
var params = {
   soapDoc: soapDoc,
   asyncMode: true,
   noBusyOverlay: true,
   callback: respCallback,
   errorCallback: respErrorCallback
this._gettingVoiceInfo = true;

In this case the callback would parse the response for GetVoiceInfoResponse.phones.

Registering the click to call dialog with phone objects

In order to get your click to call dialog to be invoked when an email or contact has a phone number your zimlet needs to implement the following methods: 

MyClick2CallZimlet.prototype.match = function(line, startIndex) {
var re = this.RE;
	re.lastIndex = startIndex;
	var m = re.exec(line);
	if (!m) { return m; }

var phone = m[0]
	// bug 73264, don't identify long digit sequence (length > 10) without separators as phone number
	if (phone.length > 10 &&
		phone[0] != "+"   &&
		!(AjxUtil.arrayContains(phone, " ")) &&
		!(AjxUtil.arrayContains(phone, ".")) &&
		!(AjxUtil.arrayContains(phone, "-"))) {
			return null;
	} else {
		m[0] = phone;
		return m;

Then handle your matches by implementing the clicked method:

MyClick2CallZimlet.prototype.clicked = function(myElement, toPhoneNumber) { this.toPhoneNumber = toPhoneNumber; this._showFromPhoneDlg(); };

Your zimlet XML configuration should have something like:

<contentObject type="phone">
			<regex attrs="g">\+?\(?\b\d([0-9\(\)\.\s\-]){8,20}\d\b</regex>

Presence Integration

In Z8 presence information is integrated into the “Email Contact Details” zimlet and displayed on the contact card when a user hovers over an email address. In order to add presence to the email zimlet, you need to register your zimlet that is providing presence as a subscriber. The email zimlet will notify other zimlets that implement “onEmailHoverOver”. An example of setting up presence for your zimlet:

MyPresenceZimlet.prototype.onEmailHoverOver = function(emailZimlet) { emailZimlet.addSubscriberZimlet(this, false, {presenceCallback: this.getPresence.bind(this)}); }

Your getPresence method then might make a REST call to retrieve the presence based on the email address which is being hovered. The presenceCallback function will be registered by the email zimlet and handle presence calls and caching.

Jump to: navigation, search