RainLoop / rainloop-webmail

Simple, modern & fast web-based email client
http://rainloop.net
MIT License
4.07k stars 873 forks source link

How can i export address book by email address without authen ? (vcf format) #2223

Open mean-cj opened 1 year ago

mean-cj commented 1 year ago

Dear Rainloop Team

I need create a automation script export the address book for any email accounts without authentication. example for web control panel migration to another server.

I create a php script, My solution export work only "cvs" format. Do you have solution, API for export the vcf format ?

How to solve this ?

PHP Fatal error:  Uncaught Error: Class 'SabreForRainLoop\VObject\Component\VCard' not found in /var/www/html/rainloop-book.php:10
Stack trace:
#0 {main}
  thrown in /var/www/html/rainloop-export.php on line 10

Fatal error: Uncaught Error: Class 'SabreForRainLoop\VObject\Component\VCard' not found in /var/www/html/rainloop-book.php:10
Stack trace:
#0 {main}
  thrown in /var/www/html/rainloop-export.php on line 10

rainloop-export.php

<?php
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
$_ENV['RAINLOOP_INCLUDE_AS_API'] = true;
include '/var/www/html/rainloop/index.php';

$oConfig =  \RainLoop\Api::Config();
$sDsn = \trim($oConfig->Get('contacts', 'pdo_dsn', ''));
$sUser = \trim($oConfig->Get('contacts', 'pdo_user', ''));
$sPassword = (string) $oConfig->Get('contacts', 'pdo_password', '');
$sDsnType = $oAction->ValidateContactPdoType(\trim($oConfig->Get('contacts', 'type', 'sqlite')));
if ('sqlite' === $sDsnType) {
  $oDriver = new \RainLoop\Providers\AddressBook\PdoAddressBook(
    'sqlite:' . APP_PRIVATE_DATA . 'AddressBook.sqlite',
    '',
    '',
    'sqlite'
  );
} else {
  $oDriver = new \RainLoop\Providers\AddressBook\PdoAddressBook($sDsn, $sUser, $sPassword, $sDsnType);
}

$oAddressBookProvider = new \RainLoop\Providers\AddressBook($oDriver);
$oAddressBookProvider->Export('email@domain.com', 'vcf'); 
or
$oDriver->Export('email@domain.com','cvs');

app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php

    public function Export($sEmail, $sType = 'vcf')
    {
        $this->SyncDatabase();

        $iUserID = $this->getUserId($sEmail);
        if (0 >= $iUserID)
        {
            return false;
        }

        $bVcf = 'vcf' === $sType;
        $bCsvHeader = true;

        $aDatabaseSyncData = $this->prepearDatabaseSyncData($iUserID);
        if (\is_array($aDatabaseSyncData) && 0 < \count($aDatabaseSyncData))
        {
            foreach ($aDatabaseSyncData as $mData)
            {
                if ($mData && isset($mData['id_contact'], $mData['deleted']) && !$mData['deleted'])
                {
                    $oContact = $this->GetContactByID($sEmail, $mData['id_contact']);
                    if ($oContact)
                    {
                        if ($bVcf)
                        {
                            echo $oContact->ToVCard();
                        }
                        else
                        {
                            echo $oContact->ToCsv($bCsvHeader);
                            $bCsvHeader = false;
                        }
                    }
                }
            }
        }

        return true;
    }

/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php

    public function ToVCard($sPreVCard = '', $oLogger = null)
    {
        $this->UpdateDependentValues();

        if (!\class_exists('SabreForRainLoop\DAV\Client'))
        {
            # return ''; <<< i try to comment this.
        }

        if ("\xef\xbb\xbf" === \substr($sPreVCard, 0, 3))
        {
            $sPreVCard = \substr($sPreVCard, 3);
        }

        $oVCard = null;
        if (0 < \strlen($sPreVCard))
        {
            try
            {
                $oVCard = \SabreForRainLoop\VObject\Reader::read($sPreVCard);
            }
            catch (\Exception $oExc)
            {
                if ($oLogger)
                {
                    $oLogger->WriteException($oExc);
                    $oLogger->WriteDump($sPreVCard);
                }
            }
        }

Thank you.

mean-cj commented 1 year ago

Rainloop Export/Import Address book without authentication. (csv format) please note this script not check duplicate contact name or email address.

<?php

error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
$_ENV['RAINLOOP_INCLUDE_AS_API'] = true;
include '/var/www/html/rainloop/index.php';

$oActions = \RainLoop\Actions::NewInstance();

$oConfig =  \RainLoop\Api::Config();
$sDsn = \trim($oConfig->Get('contacts', 'pdo_dsn', ''));
$sUser = \trim($oConfig->Get('contacts', 'pdo_user', ''));
$sPassword = (string) $oConfig->Get('contacts', 'pdo_password', '');
$sDsnType = $oActions->ValidateContactPdoType(\trim($oConfig->Get('contacts', 'type', 'sqlite')));
if ('sqlite' === $sDsnType) {
  $oDriver = new \RainLoop\Providers\AddressBook\PdoAddressBook(
    'sqlite:' . APP_PRIVATE_DATA . 'AddressBook.sqlite',
    '',
    '',
    'sqlite'
  );
} else {
  $oDriver = new \RainLoop\Providers\AddressBook\PdoAddressBook($sDsn, $sUser, $sPassword, $sDsnType);
}

$oAddressBookProvider = new \RainLoop\Providers\AddressBook($oDriver);

/*
|--------------------------------------------------------------------------
| Export
|--------------------------------------------------------------------------
*/
ob_start();
$oAddressBookProvider->Export('export@domain.com', 'csv');
$data = ob_get_clean();
file_put_contents('address_book.csv', $data);

/*
|--------------------------------------------------------------------------
| Import
|--------------------------------------------------------------------------
*/
$email_address_to_import = 'import@domain.com';
if ($oAddressBookProvider && $oAddressBookProvider->IsActive()) {

  @\setlocale(LC_CTYPE, 'en_US.UTF-8');

  if (($mData = fopen("address_book.csv", "rb")) !== FALSE) {

    $sFileStart = @\fread($mData, 20);
    \rewind($mData);

    $sDelimiter = ((int) \strpos($sFileStart, ',') > (int) \strpos($sFileStart, ';')) ? ',' : ';';

    while (false !== ($mRow = \fgetcsv($mData, 5000, $sDelimiter, '"'))) {
      if (null === $aHeaders) {
        if (3 >= \count($mRow)) {
          return 0;
        }

        $aHeaders = $mRow;

        foreach ($aHeaders as $iIndex => $sHeaderValue) {
          $aHeaders[$iIndex] = \MailSo\Base\Utils::Utf8Clear($sHeaderValue);
        }
      } else {
        $aNewItem = array();
        foreach ($aHeaders as $iIndex => $sHeaderValue) {
          $aNewItem[$sHeaderValue] = isset($mRow[$iIndex]) ? $mRow[$iIndex] : '';
        }

        $aData[] = $aNewItem;
      }
    }
  }

  if (\is_resource($mData)) {
    @\fclose($mData);
  }

  if (\is_array($aData) && 0 < \count($aData)) {
    echo   $iCount = $oAddressBookProvider->ImportCsvArray($email_address_to_import, $aData);
  }
}