OX6:MailNotify Bundle
Open-Xchange Mail Push
This package handles external notifications of new mail to send push requests to mobile devices.
Description
This Bundle is currently only able to cooperate with the mail notification functionality of cyrus-imapd, but this will change in a way, that future versions will be configurable on what kind of notification protocol is required.
At the moment, this bundle listens on the address and port as configured in /opt/open-xchange/etc/groupware/push_mailnotify.properties accepting UDP datagrams following the format as used in the cyrus notifyd:
notifyd/notifyd.c: method NUL class NUL priority NUL user NUL mailbox NUL nopt NUL N(option NUL) message NUL
and the only information which is currently being evaluated is the fourth one, the username.
Install on OX AppSuite
Debian GNU/Linux 11.0
Add the following entry to /etc/apt/sources.list.d/open-xchange.list if not already present:
deb https://software.open-xchange.com/products/stable/DebianBullseye/ /
# if you have a valid maintenance subscription, please uncomment the
# following and add the ldb account data to the url so that the most recent
# packages get installed
# deb https://[CUSTOMERID:PASSWORD]@software.open-xchange.com/products/stable/updates/DebianBullseye/ /
and run
$ apt-get update $ apt-get install open-xchange-push-mailnotify
Debian GNU/Linux 12.0
Add the following entry to /etc/apt/sources.list.d/open-xchange.list if not already present:
deb https://software.open-xchange.com/products/stable/DebianBookworm/ /
# if you have a valid maintenance subscription, please uncomment the
# following and add the ldb account data to the url so that the most recent
# packages get installed
# deb https://[CUSTOMERID:PASSWORD]@software.open-xchange.com/products/stable/updates/DebianBookworm/ /
and run
$ apt-get update $ apt-get install open-xchange-push-mailnotify
Install on OX App Suite
Debian GNU/Linux 11.0
Add the following entry to /etc/apt/sources.list.d/open-xchange.list if not already present:
deb https://LDBACCOUNT:LDBPASSWD@software.open-xchange.com/products/appsuite/stable/backend//DebianBullseye/ /
and run
$ apt-get update $ apt-get install open-xchange-push-mailnotify
Debian GNU/Linux 12.0
Add the following entry to /etc/apt/sources.list.d/open-xchange.list if not already present:
deb https://LDBACCOUNT:LDBPASSWD@software.open-xchange.com/products/appsuite/stable/backend//DebianBookworm/ /
and run
$ apt-get update $ apt-get install open-xchange-push-mailnotify
Configuration
On the server running cyrus, add the following to /etc/imapd.conf:
mailnotifier: log
In /etc/cyrus.conf take care, that cyrus own notifyd is NOT in use. If it is not commented, either do that or remove it completely.
Example:
Note: The path to the socket in this example is valid for Redhat Enterprise Linux. On Debian it is /var/lib/cyrus/socket/notify. It might be different on your installation. Please check the default in /etc/imapd.conf on your system.
# this is only necessary if using notifications # notify cmd="notifyd" listen="/var/lib/imap/socket/notify" proto="udp" prefork=1
Install the program socat. Socat is a Multipurpose relay (see http://www.dest-unreach.org/socat/) which must be used to relay the udb datagrams from the unix domain socket to the open-xchange push bundle.
To redirect the notifications to the open-xchange server, socat must be started like this:
socat -u -4 UNIX-RECV:/var/lib/imap/socket/notify,unlink-early,perm-early=777,type=2 \ UDP-SENDTO:<YOUROXIP>:<YOURPUSHPORT>
To debug whether cyrus sends messages, you might want to add debugging to socat:
socat -d -d -d -D -v -u -4 UNIX-RECV:/var/lib/imap/socket/notify,unlink-early,perm-early=777,type=2 \ UDP-SENDTO:<YOUROXIP>:<YOURPUSHPORT>
Example Initscript for Debian
The following initscript can be used to start the socat tunnel on debian. A file /etc/default/ox-push can be created to define parameters such as DAEMON_ARGS.
After copying the script to /etc/init.d/ox-push do the following:
$ chmod 755 /etc/init.d/ox-push $ update-rc.d ox-push defaults
#! /bin/sh ### BEGIN INIT INFO # Provides: ox-push # Required-Start: $local_fs $remote_fs open-xchange-groupware # Required-Stop: $local_fs $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: UDP Tunnel for Open-Xchange mail push # Description: Tunnel UDP Datagrams from cyrus notify unix socket # to Open-Xchange Mail Push bundle ### END INIT INFO # Do NOT "set -e" # PATH should only include /usr/* if it runs after the mountnfs.sh script PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="Open-Xchange Push Tunnel" NAME=socat DAEMON=/usr/bin/$NAME DAEMON_ARGS="-u -4 UNIX-RECV:/var/lib/cyrus/socket/notify,unlink-early,perm-early=777,type=2 UDP-SENDTO:localhost:23420" PIDFILE=/var/run/$NAME.pid SCRIPTNAME=/etc/init.d/$NAME # Exit if the package is not installed [ -x "$DAEMON" ] || exit 0 # Read configuration variable file if it is present [ -r /etc/default/$NAME ] && . /etc/default/$NAME # Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh # Define LSB log_* functions. # Depend on lsb-base (>= 3.0-6) to ensure that this file is present. . /lib/lsb/init-functions # # Function that starts the daemon/service # do_start() { # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started start-stop-daemon --start -b --quiet -m --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ || return 1 start-stop-daemon --start -b --quiet -m --pidfile $PIDFILE --exec $DAEMON -- \ $DAEMON_ARGS \ || return 2 # Add code here, if necessary, that waits for the process to be ready # to handle requests from services started subsequently which depend # on this one. As a last resort, sleep for some time. } # # Function that stops the daemon/service # do_stop() { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME RETVAL="$?" [ "$RETVAL" = 2 ] && return 2 # Many daemons don't delete their pidfiles when they exit. rm -f $PIDFILE return "$RETVAL" } case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; restart|force-reload) # # If the "reload" option is implemented then remove the # 'force-reload' alias # log_daemon_msg "Restarting $DESC" "$NAME" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 exit 3 ;; esac :
Example Initscript for Redhat/SUSE
After copying the script to /etc/init.d/ox-push do the following:
$ chmod 755 /etc/init.d/ox-push
and on Redhat
$ chkconfig --level 35 ox-push on
on SUSE
$ insserv ox-push
#!/bin/bash # # LSB system startup script for service/daemon socat tunnel # Based on initscript skeleton.compat as shipped with [open]SUSE. # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or (at # your option) any later version. # # This library is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, # USA. # # /etc/init.d/ox-push # LSB compatible service control script; see http://www.linuxbase.org/spec/ # # Note: This template uses functions rc_XXX defined in /etc/rc.status on # UnitedLinux/SUSE/Novell based Linux distributions. However, it will work # on other distributions as well, by using the LSB (Linux Standard Base) # or RH functions or by open coding the needed functions. # Read http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/ if you prefer not # to use this template. # # chkconfig: 345 99 00 # description: Open Xchange Groupware Daemon # ### BEGIN INIT INFO # Provides: ox-push # Required-Start: $syslog $remote_fs open-xchange-groupware # Required-Stop: $syslog $remote_fs # Default-Start: 3 4 5 # Default-Stop: 0 1 2 6 # Short-Description: Open Xchange Groupware Daemon # Description: UDP Tunnel for Open-Xchange mail push ### END INIT INFO # Note: Special treatment of stop for LSB conformance PIDFILE=ox-push.pid SOCATBIN=/usr/bin/socat SOCATARGS="-u -4 UNIX-RECV:/var/lib/imap/socket/notify,unlink-early,perm-early=777,type=2 UDP-SENDTO:localhost:23420" test -x $SOCATBIN || { echo "$SOCATBIN not installed"; if [ "$1" = "stop" ]; then exit 0; else exit 5; fi; } # Source LSB init functions # providing start_daemon, killproc, pidofproc, # log_success_msg, log_failure_msg and log_warning_msg. # This is currently not used by UnitedLinux based distributions and # not needed for init scripts for UnitedLinux only. If it is used, # the functions from rc.status should not be sourced or used. #. /lib/lsb/init-functions # Shell functions sourced from /etc/rc.status: # rc_check check and set local and overall rc status # rc_status check and set local and overall rc status # rc_status -v be verbose in local rc status and clear it afterwards # rc_status -v -r ditto and clear both the local and overall rc status # rc_status -s display "skipped" and exit with status 3 # rc_status -u display "unused" and exit with status 3 # rc_failed set local and overall rc status to failed # rc_failed <num> set local and overall rc status to <num> # rc_reset clear both the local and overall rc status # rc_exit exit appropriate to overall rc status # rc_active checks whether a service is activated by symlinks # Use the SUSE rc_ init script functions; # emulate them on LSB, RH and other systems # Default: Assume sysvinit binaries exist start_daemon() { /sbin/start_daemon ${1+"$@"}; } killproc() { /sbin/killproc ${1+"$@"}; } pidofproc() { /sbin/pidofproc ${1+"$@"}; } checkproc() { /sbin/checkproc ${1+"$@"}; } if test -e /etc/rc.status; then # SUSE rc script library . /etc/rc.status else export LC_ALL=POSIX _cmd=$1 declare -a _SMSG if test "${_cmd}" = "status"; then _SMSG=(running dead dead unused unknown reserved) _RC_UNUSED=3 else _SMSG=(done failed failed missed failed skipped unused failed failed reserved) _RC_UNUSED=6 fi if test -e /lib/lsb/init-functions; then # LSB . /lib/lsb/init-functions echo_rc() { if test ${_RC_RV} = 0; then log_success_msg " [${_SMSG[${_RC_RV}]}] " else log_failure_msg " [${_SMSG[${_RC_RV}]}] " fi } # TODO: Add checking for lockfiles checkproc() { return pidofproc ${1+"$@"} >/dev/null 2>&1; } elif test -e /etc/init.d/functions; then # RHAT . /etc/init.d/functions echo_rc() { #echo -n " [${_SMSG[${_RC_RV}]}] " if test ${_RC_RV} = 0; then success " [${_SMSG[${_RC_RV}]}] " else failure " [${_SMSG[${_RC_RV}]}] " fi } checkproc() { return status ${1+"$@"}; } start_daemon() { return daemon ${1+"$@"}; } else # emulate it echo_rc() { echo " [${_SMSG[${_RC_RV}]}] "; } fi rc_reset() { _RC_RV=0; } rc_failed() { if test -z "$1"; then _RC_RV=1; elif test "$1" != "0"; then _RC_RV=$1; fi return ${_RC_RV} } rc_check() { return rc_failed $? } rc_status() { rc_failed $? if test "$1" = "-r"; then _RC_RV=0; shift; fi if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi if test "$1" = "-v"; then echo_rc; shift; fi if test "$1" = "-r"; then _RC_RV=0; shift; fi return ${_RC_RV} } rc_exit() { exit ${_RC_RV}; } rc_active() { if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi return 1 } fi # Reset status of this service rc_reset # Return values acc. to LSB for all commands but status: # 0 - success # 1 - generic or unspecified error # 2 - invalid or excess argument(s) # 3 - unimplemented feature (e.g. "reload") # 4 - user had insufficient privileges # 5 - program is not installed # 6 - program is not configured # 7 - program is not running # 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) # # Note that starting an already running service, stopping # or restarting a not-running service as well as the restart # with force-reload (in case signaling is not supported) are # considered a success. tstatus() { if [ ! -f /var/run/$PIDFILE ]; then return 3 else read PID < /var/run/$PIDFILE test -z "$PID" && { echo "unable to read pid"; return 3; } if ! ps $PID > /dev/null; then return 3 fi fi return 0 } case "$1" in start) echo -n "Starting ox push " ## Start daemon with startproc(8). If this fails ## the return value is set appropriately by startproc. $SOCATBIN $SOCATARGS 2>&1 & echo $! > /var/run/$PIDFILE # Remember status and be verbose rc_status -v ;; stop) echo -n "Shutting down ox push " ## Stop daemon with killproc(8) and if this fails ## killproc sets the return value according to LSB. if [ ! -f /var/run/$PIDFILE ]; then echo "service not running" else read PID < /var/run/$PIDFILE test -z "$PID" && { echo "unable to read pid"; exit 1; } if ! ps $PID > /dev/null; then echo "service not running" else kill -TERM $PID fi fi # Remember status and be verbose rc_status -v ;; try-restart|condrestart) ## Do a restart only if the service was active before. ## Note: try-restart is now part of LSB (as of 1.9). ## RH has a similar command named condrestart. if test "$1" = "condrestart"; then echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}" fi $0 status if test $? = 0; then $0 restart else rc_reset # Not running is not a failure. fi # Remember status and be quiet rc_status ;; restart) ## Stop the service and regardless of whether it was ## running or not, start it again. $0 stop $0 start # Remember status and be quiet rc_status ;; force-reload) ## Signal the daemon to reload its config. Most daemons ## do this on signal 1 (SIGHUP). ## If it does not support it, restart the service if it ## is running. echo -n "Reload ox push " ## if it supports it: #killproc -p $PIDFILE -HUP $OX_BIN #touch /var/run/FOO.pid #rc_status -v ## Otherwise: $0 try-restart rc_status ;; reload) ## Like force-reload, but if daemon does not support ## signaling, do nothing (!) # If it supports signaling: echo -n "Reload ox push " #killproc -p $PIDFILE -HUP $OX_BIN #touch /var/run/FOO.pid #rc_status -v ## Otherwise if it does not support reload: rc_failed 3 rc_status -v ;; status) echo -n "Checking for ox push " ## Check status with checkproc(8), if process is running ## checkproc will return with exit status 0. # Return value is slightly different for the status command: # 0 - service up and running # 1 - service dead, but /var/run/ pid file exists # 2 - service dead, but /var/lock/ lock file exists # 3 - service not running (unused) # 4 - service status unknown :-( # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) # NOTE: checkproc returns LSB compliant status values. tstatus # NOTE: rc_status knows that we called this init script with # "status" option and adapts its messages accordingly. rc_status -v ;; *) echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|}" exit 1 ;; esac rc_exit