Horde Email Stopped Working

AGuyInFL

Member
Jul 20, 2015
14
0
1
US
cPanel Access Level
Website Owner
My Horde email stopped sending or receiving emails. I get a /usr/local/cpanel/3rdparty/php/54/lib/php/Horde/Smtp/ error.

What steps should I take to resolve this?

I read somewhere that I need to configure the /usr/local/cpanel/base/horde/imp/config/conf.php file. How do I access it? I have access to both WHM and Virtuozzo. Any help will be appreciated.
 

AGuyInFL

Member
Jul 20, 2015
14
0
1
US
cPanel Access Level
Website Owner
OK, I found it, but what do I update in the file?

Code:
#!/usr/local/cpanel/3rdparty/bin/perl
# cpanel - bin/update_horde_config                Copyright(c) 2015 cPanel, Inc.
#                                                           All rights Reserved.
# [email protected]                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

## cpdev: rpm %post for 5.1 to /usr/local/cpanel/base/horde

package Cpanel::Bin::UpdateHorde;
use strict;

use Cpanel::AccessIds           ();
use Cpanel::Binaries            ();
use Cpanel::Config::LoadCpConf  ();
use Cpanel::Config::Users       ();
use Cpanel::DAV::Defaults       ();
use Cpanel::Horde::DB           ();
use Cpanel::MD5                 ();
use Cpanel::Quota::Temp         ();
use Cpanel::RPM::Versions::File ();
use Cpanel::SafeDir::MK         ();
use Cpanel::SafeFile            ();
use Cpanel::StringFunc::Fmt     ();
use Whostmgr::Email             ();

use Getopt::Long ();
use Cwd;

use Cpanel::Locale 'lh';

my $ulcdir   = '/usr/local/cpanel';
my $DIR      = "$ulcdir/base";
my $hordedir = "$ulcdir/base/horde";

my ( $opt_user, $opt_full, $opt_progress, $opt_dbonly, $opt_create_defaults, $opt_quiet, $opt_help );

__PACKAGE__->run(@ARGV) unless caller;

sub run {
    my @args = @_;

    my $getopt_status = Getopt::Long::GetOptionsFromArray(
        \@args,
        'user:s'          => \$opt_user,
        'full'            => \$opt_full,
        'progress'        => \$opt_progress,
        'dbonly'          => \$opt_dbonly,
        'create-defaults' => \$opt_create_defaults,
        'quiet'           => \$opt_quiet,
        'help'            => \$opt_help,
      )
      and !$opt_help
      or _usage();

    my $horde_creator = Cpanel::Horde::DB->new( { callback => \&_callback, full => $opt_full, run_php_ini => 1 } );

    unless ($opt_dbonly) {
        update_conf(0);
    }

    # Make sure the db is there only print error if it's an unknown error.
    $ENV{LC_ALL} = 'C';

    my $users = Cpanel::Config::Users::getcpusers();

    if ( defined $opt_user ) {
        $users = [ grep { $_ eq $opt_user } @$users ];
        if ( [email protected]$users ) {
            die "Couldn't find an account called $opt_user\n";
        }
    }

    $users = [ sort @$users ];

    info( lh()->maketext( 'Running database checks for [numf,_1] account(s) …', scalar(@$users) ) );

    my ( @failed, @succeeded, @no_changes_needed );
    for my $n ( 0 .. $#$users ) {
        my $user = $users->[$n];

        next if $user eq 'root';    # not needed and would cause a premature exit

        local $ENV{PROGRESS_INFO} = sprintf( '% 20s (%d/%d) | ', $user, $n + 1, $#$users + 1 );

        # Grab a preview of whether changes are going to be needed so we can decide whether
        # to disable the quota or not. This should be faster than just blindly disabling it
        # every time.
        my $changes_needed = (
            $opt_create_defaults || Cpanel::AccessIds::do_as_user(
                $user,
                sub {
                    $horde_creator->changes_needed();
                }
            )
        );

        my $tempquota = Cpanel::Quota::Temp->new( user => $user );
        $tempquota->disable() if $changes_needed;

        my $email_accts = Whostmgr::Email::list_pops_for($user);
        my @all_possible_horde_ids_for_user = ( $user, @$email_accts );

        eval {
            Cpanel::AccessIds::do_as_user_with_exception(
                $user,
                sub {
                    $horde_creator->create();

                    if ($opt_create_defaults) {
                        for my $principal (@all_possible_horde_ids_for_user) {
                            my $resp = Cpanel::DAV::Defaults::create_calendars_and_address_books($principal);
                            die $resp->as_string if !$resp->meta->ok;
                        }
                    }
                }
            );
        };
        if ( my $exception = [email protected] ) {
            info($exception);
            push @failed, $user;
        }
        elsif ($changes_needed) {
            push @succeeded, $user;
        }
        else {
            push @no_changes_needed, $user;
        }

        $tempquota->restore() if $changes_needed;
    }

    info( '-' x 72 );
    info( lh()->maketext('Summary:') );
    info();
    info( lh()->maketext( 'Ran database checks on [numf,_1] account(s).', scalar(@$users) ) );
    info();
    info( lh()->maketext( 'There were [numf,_1] accounts with failures during this process (see above): [_2]', scalar(@failed),            _pretty_username_list( \@failed ) ) );
    info( lh()->maketext( 'There were [numf,_1] accounts successfully processed: [_2]',                        scalar(@succeeded),         _pretty_username_list( \@succeeded ) ) );
    info( lh()->maketext( 'There were [numf,_1] accounts that did not need any work done: [_2]',               scalar(@no_changes_needed), _pretty_username_list( \@no_changes_needed ) ) );

    return;
}

sub update_conf {
    my $update = shift;
    my $cpconf = Cpanel::Config::LoadCpConf::loadcpconf();

    my $conf = 'config/conf.php';

    my $aspell = -x '/usr/bin/aspell' ? '/usr/bin/aspell' : '/usr/bin/hunspell';

    my $horde_conf = "$hordedir/$conf";
    info("horde conf: $hordedir/$conf");
    my $conf_lock = Cpanel::SafeFile::safeopen( \*HORDECONF, '<', $horde_conf );

    if ( !$conf_lock ) {
        die("Unable to read $horde_conf: $!");
    }
    my @horde_conf_lines = <HORDECONF>;
    Cpanel::SafeFile::safeclose( \*HORDECONF, $conf_lock );

    my $lock = Cpanel::SafeFile::safeopen( \*HORDECONF, '>', $horde_conf );
    if ( !$lock ) {
        die("Unable to write $horde_conf: $!");
    }

    my $tmpdb_config = <<'EOS';
if (getenv('CPANEL_HORDE_TMPDB')) {
    $conf['sql']['database'] = getenv('CPANEL_HORDE_TMPDB');
}
EOS

    # use a oneliner to remove/update it easier
    $tmpdb_config =~ s{[\n\s]+}{ }g;
    $tmpdb_config .= "\n";

    my $handled_sql_section;
    foreach my $line (@horde_conf_lines) {
        if ( $line =~ m/^\s*\$\Qconf['sql']/ ) {
            if ( !$handled_sql_section++ ) {
                print HORDECONF <<'SQL';
$conf['sql']['phptype']  = 'sqlite';
$conf['sql']['database'] = posix_getpwuid( posix_getuid() )['dir'] . '/.cphorde/horde.sqlite';
$conf['sql']['mode']     = 0600;
$conf['sql']['charset']  = 'UTF-8';
SQL
            }
        }
        elsif ( $line =~ m/^\s*\$\Qconf['spell']['params']['path']\E/ ) {
            print HORDECONF q{$conf['spell']['params']['path'] = '} . $aspell . "';\n";
        }
        elsif ( $line =~ m/CPANEL_HORDE_TMPDB/ || $line =~ /^\s*$/ ) {
            next;
        }
        else {
            print HORDECONF $line;
        }
    }

    print HORDECONF "\n" . $tmpdb_config;

    Cpanel::SafeFile::safeclose( \*HORDECONF, $lock );

    # TODO: check if $conf.rpmsave or .oldsave exists (edited file), 3-way merge
    # if !$update apply the typical 1->5 changes, like Upcase firstchar of some static values (sql => Sql)
    # ...

    if ($handled_sql_section) {
        system 'chmod', '644', "$hordedir/$conf";    # The file no longer contains a password
        info('Successfully updated the sql section of the Horde configuration.');
    }
    else {
        info('Failed to update the sql section of the Horde configuration.');    # The file might still contain a password
    }

    return;
}

sub filesame {
    my ( $f1, $f2 ) = @_;

    # handle undefined cases
    return 1 if !defined($f1) && !defined($f2);
    return 0 if !defined($f1) || !defined($f2);

    # now both values are defined
    # handle non existing case
    return 1 if !-e $f1 && !-e $f2;
    return 0 if !-e $f1 || !-e $f2;

    my $md5a = Cpanel::MD5::getmd5sum($f1);
    my $md5b = Cpanel::MD5::getmd5sum($f2);

    return $md5a eq $md5b;
}

# PROGRESS: Only print if --progress is specified
#     INFO: Always print
sub _callback {
    my ( $type, $msg ) = @_;
    return if $opt_quiet;
    if ( $type eq 'PROGRESS' ) {
        my $line = $ENV{PROGRESS_INFO} . $msg;
        if ($opt_progress) {
            info($line);
        }
    }
    elsif ( $type eq 'INFO' ) {
        info($msg);
    }
    return;
}

sub _usage {
    die <<EOF;
Usage: $0 [--user=...]

This script is responsible for:
  1. Creating the per-user SQLite databases for horde.
  2. Keeping the Horde tables up to date with schema changes.
  3. Assuring critical horde config variables are set correctly.

It should be run:
  - After updating any Horde components that resulted in a change of
    db schema (with --full)
  - After creating a new cPanel account (with --user=<thatuser>)
  - Routinely (with no arguments) in order to make sure all users
    have a Horde SQLite database.
  - If the Horde database(s) ever need to be repaired after having
    tables dropped/lost (with --full)

These uses of update_horde_config happen automatically, and administrators
should only need to run it manually if they believe something has gone wrong
with the automated run or with a Horde database.

Arguments:

        --user=...  (optional) Allows you to specify that you only want the per-user
                    database operations to be performed for a single user, not for all
                    users. The global operations (updating conf) will still be performed
                    regardless of whether this option is specified or not.

            --full  (optional) Check and upgrade the table schema instead of just checking
                    that the per-user databases exist on disk. This schema check used to be
                    done on every run of update_horde_config, but now that each user has
                    their own copy of the Horde database, this was too time-consuming.
                    The expectation now is that any updates to Horde that require schema
                    upgrades (which are exceedingly rare so far) will include a one-time
                    task to run update_horde_config --full.

        --progress  (optional) Report progress as each user is processed (noisy).

          --dbonly  (optional) Only attempt to check / fix database problems; don't update
                    the Horde system-wide configuration file.

--create-defaults  (optional) When creating or checking the database, ensure that the
                    default address book and calendar are created. This option is suitable
                    for manual use in the case where you are deleting and re-creating an
                    entire database and want the default calendars and address books
                    back.

           --quiet  Keep output to a minimum. Errors or warnings that are produced during
                    the process may still slip through, but the normal output explaining
                    what's being done will be suppressed.

Examples:

                    Please see http://go.cpanel.net/hordetroubleshoot for example usage.
EOF
}

# Using this instead of Cpanel::Logger because Cpanel::Logger usage in this script will
# result in bad-looking output when run during/after upcp.
sub info {
    my ($msg) = @_;
    return if $opt_quiet;
    $msg ||= '';
    chomp $msg;
    return print "$msg\n";
}

sub _pretty_username_list {
    my ($users) = @_;
    my $wrapped = Cpanel::StringFunc::Fmt::wrap( join( ', ', @$users ), 68 );
    $wrapped =~ s/^/    /gm;
    return "\n" . $wrapped . "\n";
}

1;
 

AGuyInFL

Member
Jul 20, 2015
14
0
1
US
cPanel Access Level
Website Owner
The issue has been resolved. It was caused by and I quote: "The issue was caused by outbound DNS requests timing out, due to a firewall rule having been triggered. This also caused a number of stacked cPanel maintenance attempts..."
 

cPanelMichael

Administrator
Staff member
Apr 11, 2011
47,884
2,243
463
Hello :)

I'm happy to see the issue is now resolved. Thank you for updating us with the outcome.