protected function actionSyncContacts($params) { \GO::$ignoreAclPermissions = true; //allow this script access to all \GO::$disableModelCache = true; //for less memory usage ini_set('max_execution_time', '300'); $ab = \GO\Addressbook\Model\Addressbook::model()->findSingleByAttribute('users', '1'); //\GO::t('users','base')); if (!$ab) { $ab = new \GO\Addressbook\Model\Addressbook(); $ab->name = \GO::t('users'); $ab->users = true; $ab->save(); } $stmt = User::model()->find(); while ($user = $stmt->fetch()) { $contact = $user->contact(); if (!$contact) { \GO::output("Creating contact for " . $user->username); $contact = new \GO\Addressbook\Model\Contact(); $contact->go_user_id = $user->id; $contact->addressbook_id = $ab->id; } else { \GO::output("Updating contact for " . $user->username); } $attr = $user->getAttributes(); unset($attr['id']); $contact->setAttributes($attr); $contact->save(); } \GO::output("Done!"); //return array('success' => true); }
protected function actionBatchSend($params) { $this->requireCli(); $this->_sentEmails = array(); \GO::$disableModelCache = true; $mailing = \GO\Addressbook\Model\SentMailing::model()->findByPk($params['mailing_id']); if (!$mailing) { throw new \Exception("Mailing not found!\n"); } \GO::session()->runAs($mailing->user_id); echo 'Status: ' . $mailing->status . "\n"; if (empty($mailing->status)) { echo "Starting mailing at " . \GO\Base\Util\Date::get_timestamp(time()) . "\n"; $mailing->reset(); } elseif (!empty($params['restart'])) { echo "Restarting mailing at " . \GO\Base\Util\Date::get_timestamp(time()) . "\n"; $mailing->reset(); } elseif ($mailing->status == \GO\Addressbook\Model\SentMailing::STATUS_PAUSED) { echo "Resuming mailing at " . \GO\Base\Util\Date::get_timestamp(time()) . "\n"; $mailing->status = \GO\Addressbook\Model\SentMailing::STATUS_RUNNING; $mailing->save(); } $htmlToText = new \GO\Base\Util\Html2Text(); //$addresslist = \GO\Addressbook\Model\Addresslist::model()->findByPk($mailing->addresslist_id); $mimeData = file_get_contents(\GO::config()->file_storage_path . $mailing->message_path); $message = \GO\Base\Mail\Message::newInstance()->loadMimeMessage($mimeData); $joinCriteria = \GO\Base\Db\FindCriteria::newInstance()->addRawCondition('t.id', 'a.account_id'); $findParams = \GO\Base\Db\FindParams::newInstance()->single()->join(\GO\Email\Model\Alias::model()->tableName(), $joinCriteria, 'a')->criteria(\GO\Base\Db\FindCriteria::newInstance()->addCondition('id', $mailing->alias_id, '=', 'a')); if ($mailing->campaign_id > 0 && \GO::modules()->isAvailable('campaigns')) { $account = new \GO\Email\Model\Account(); $account->username = \GO::config()->campaigns_imap_user; $account->password = \GO::config()->campaigns_imap_pass; $account->host = \GO::config()->campaigns_imap_server; $account->port = \GO::config()->campaigns_imap_port; $account->smtp_username = \GO::config()->campaigns_smtp_user; $account->smtp_password = \GO::config()->campaigns_smtp_pass; $account->smtp_host = \GO::config()->campaigns_smtp_server; $account->smtp_port = \GO::config()->campaigns_smtp_port; $message->setFrom(\GO::config()->campaigns_from); } else { $account = \GO\Email\Model\Account::model()->find($findParams); if (!$account->store_password && !empty($mailing->temp_pass)) { $account->smtp_password = $mailing->temp_pass; } } $mailer = \GO\Base\Mail\Mailer::newGoInstance(\GO\Email\Transport::newGoInstance($account)); echo "Will send emails from " . $account->username . ".\n"; if (empty(\GO::config()->mailing_messages_per_minute)) { \GO::config()->mailing_messages_per_minute = 30; } //Rate limit to 100 emails per-minute $mailer->registerPlugin(new \Swift_Plugins_ThrottlerPlugin(\GO::config()->mailing_messages_per_minute, \Swift_Plugins_ThrottlerPlugin::MESSAGES_PER_MINUTE)); // Use AntiFlood to re-connect after 50 emails $mailer->registerPlugin(new \Swift_Plugins_AntiFloodPlugin(\GO::config()->mailing_messages_per_minute)); echo 'Sending a maximum of ' . \GO::config()->mailing_messages_per_minute . ' messages per minute' . "\n"; $failedRecipients = array(); $bodyWithTags = $message->getBody(); foreach ($mailing->contacts as $contact) { $sentMailingContactModel = \GO\Addressbook\Model\SentMailingContact::model()->findSingleByAttributes(array('sent_mailing_id' => $mailing->id, 'contact_id' => $contact->id)); if (!$sentMailingContactModel->sent) { $errors = 1; $unsubscribeHref = \GO::url('addressbook/sentMailing/unsubscribe', array('addresslist_id' => $mailing->addresslist_id, 'contact_id' => $contact->id, 'token' => md5($contact->ctime . $contact->addressbook_id . $contact->firstEmail)), false, true); $body = str_replace('%unsubscribe_href%', $unsubscribeHref, $bodyWithTags); //curly brackets don't work inside links in browser wysiwyg editors. $templateModel = \GO\Addressbook\Model\Template::model(); $templateModel->htmlSpecialChars = false; $body = $templateModel->replaceCustomTags($body, array('unsubscribe_link' => '<a href="' . $unsubscribeHref . '" target="_blank">' . \GO::t("unsubscription", "addressbook") . '</a>'), true); $templateModel->htmlSpecialChars = true; try { if (!$contact->email_allowed) { echo "Skipping contact " . $contact->firstEmail . " because newsletter sending is disabled in the addresslists tab.\n\n"; } elseif (empty($contact->firstEmail)) { echo "Skipping contact " . $contact->name . " no e-mail address was set.\n\n"; } else { $body = \GO\Addressbook\Model\Template::model()->replaceContactTags($body, $contact); $message->setTo($contact->firstEmail, $contact->name); $message->setBody($body); $plainTextPart = $message->findPlainTextBody(); if ($plainTextPart) { $htmlToText->set_html($body); $plainTextPart->setBody($htmlToText->get_text()); } // Check mail limit $nSentMails = \GO::config()->get_setting('campaigns_number_sent_mails', 0); if ($mailing->campaign_id > 0 && $nSentMails >= \GO::config()->campaigns_max_mails_per_period) { $this->_pauseMailing($mailing->id); echo "Error for " . $contact->firstEmail . ": \n"; echo str_replace('%maxMails', \GO::config()->campaigns_max_mails_per_period, \GO::t('sentMailLimitReached', 'campaigns')); exit; } $this->_sendmail($message, $contact, $mailer, $mailing); \GO::config()->save_setting('campaigns_number_sent_mails', $nSentMails + 1, 0); $errors = 0; } } catch (\Exception $e) { echo "Error for " . $contact->firstEmail . ": " . $e->getMessage() . "\n"; } if ($errors) { $mailing->errors++; $mailing->save(); } } } foreach ($mailing->companies as $company) { $sentMailingCompanyModel = \GO\Addressbook\Model\SentMailingCompany::model()->findSingleByAttributes(array('sent_mailing_id' => $mailing->id, 'company_id' => $company->id)); if (!$sentMailingCompanyModel->sent) { $errors = 1; $unsubscribeHref = \GO::url('addressbook/sentMailing/unsubscribe', array('addresslist_id' => $mailing->addresslist_id, 'company_id' => $company->id, 'token' => md5($company->ctime . $company->addressbook_id . $company->email)), true, true); $body = str_replace('%unsubscribe_href%', $unsubscribeHref, $bodyWithTags); //curly brackets don't work inside links in browser wysiwyg editors. $body = \GO\Addressbook\Model\Template::model()->replaceCustomTags($body, array('unsubscribe_link' => '<a href="' . $unsubscribeHref . '">' . \GO::t("unsubscription", "addressbook") . '</a>'), true); try { if (!$company->email_allowed) { echo "Skipping company " . $company->email . " because newsletter sending is disabled in the addresslists tab.\n\n"; } elseif (empty($company->email)) { echo "Skipping company " . $company->name . " no e-mail address was set.\n\n"; } else { $body = \GO\Addressbook\Model\Template::model()->replaceModelTags($body, $company); $message->setTo($company->email, $company->name); $message->setBody($body); $plainTextPart = $message->findPlainTextBody(); if ($plainTextPart) { $htmlToText->set_html($body); $plainTextPart->setBody($htmlToText->get_text()); } // Check mail limit $nSentMails = \GO::config()->get_setting('campaigns_number_sent_mails', 0); if ($mailing->campaign_id > 0 && $nSentMails >= \GO::config()->campaigns_max_mails_per_period) { $this->_pauseMailing($mailing->id); echo "Error for " . $contact->firstEmail . ": \n"; echo str_replace('%maxMails', \GO::config()->campaigns_max_mails_per_period, \GO::t('sentMailLimitReached', 'campaigns')); exit; } $this->_sendmail($message, $company, $mailer, $mailing); \GO::config()->save_setting('campaigns_number_sent_mails', $nSentMails + 1, 0); $errors = 0; } } catch (\Exception $e) { echo "Error for " . $company->email . ": " . $e->getMessage() . "\n"; } if ($errors) { $mailing->errors++; $mailing->save(); } } } $mailing->status = \GO\Addressbook\Model\SentMailing::STATUS_FINISHED; // Unset the temp_pass if (!empty($mailing->temp_pass)) { $mailing->temp_pass = ""; } $mailing->save(); echo "Mailing finished at " . \GO\Base\Util\Date::get_timestamp(time()) . "\n"; }
/** * * Defaults to a CSV import. * * Custom fields can be specified in the header with cf\$categoryName\$fieldName * * eg. name,attribute,cf\Test\Textfield * * Command line: * * ./groupoffice biling/order/import --file=/path/to/file.csv --delimiter=, --enclosure=" * * @param array $params */ protected function actionImport($params) { $summarylog = new \GO\Base\Component\SummaryLog(); \GO::$disableModelCache = true; //for less memory usage \GO::setMaxExecutionTime(0); \GO::session()->closeWriting(); //close writing otherwise concurrent requests are blocked. $attributeIndexMap = isset($params['attributeIndexMap']) ? $attributeIndexMap = json_decode($params['attributeIndexMap'], true) : array(); if (is_file($params['file'])) { if (!isset($params['importType'])) { $params['importType'] = 'Csv'; } $fileClassName = 'GO\\Base\\Fs\\' . $params['importType'] . 'File'; if ($params['importType'] == 'Xls' && !empty($params['maxColumnNr'])) { $importFile = new $fileClassName($params['file'], $params['maxColumnNr']); } else { $importFile = new $fileClassName($params['file']); } if (!empty($params['delimiter'])) { $importFile->delimiter = $params['delimiter']; } if (!empty($params['enclosure'])) { $importFile->enclosure = $params['enclosure']; } if (php_sapi_name() == 'cli') { if (!empty($importFile->delimiter)) { echo "Delimiter: " . $importFile->delimiter . "\n"; } if (!empty($importFile->enclosure)) { echo "Enclosure: " . $importFile->enclosure . "\n"; } echo "File: " . $importFile->path() . "\n\n"; } if (!$importFile->convertToUtf8()) { exit("ERROR: Could not convert to UTF8. Is the file writable?\n\n"); } $headers = $importFile->getRecord(); //Map the field headers to the index in the record. //eg. name=>2,user_id=>4, etc. if (empty($attributeIndexMap)) { for ($i = 0, $m = count($headers); $i < $m; $i++) { if (substr($headers[$i], 0, 3) == 'cf\\') { $cf = $this->_resolveCustomField($headers[$i]); if ($cf) { $attributeIndexMap[$i] = $cf; } } else { $attributeIndexMap[$i] = $headers[$i]; } } } while ($record = $importFile->getRecord()) { $attributes = array(); $model = false; foreach ($attributeIndexMap as $index => $attributeName) { if ($index >= 0) { $attributes[trim($attributeName)] = $record[$index]; } } if (!empty($params['updateExisting']) && !empty($params['updateFindAttributes'])) { $findBy = explode(',', $params['updateFindAttributes']); $attr = array(); foreach ($findBy as $attrib) { $attr[$attrib] = $attributes[$attrib]; } $model = \GO::getModel($this->model)->findSingleByAttributes($attr); } if (!$model) { $model = new $this->model(); } // If there are given baseparams to the importer if (isset($params['importBaseParams'])) { $baseParams = json_decode($params['importBaseParams'], true); foreach ($baseParams as $attr => $val) { $attributes[$attr] = $val; } } if ($this->beforeImport($params, $model, $attributes, $record)) { // //Unset some default attributes set in the code // $defaultAttributes = $model->defaultAttributes(); // foreach($defaultAttributes as $column => $value) // unset($model->{$column}); $columns = $model->getColumns(); foreach ($columns as $col => $attr) { if (isset($attributes[$col])) { // if($attr['gotype']=='unixtimestamp' || $attr['gotype']=='unixdate'){ // $attributes[$col]=strtotime($attributes[$col]); // if ($attr['gotype'] == 'number') { $attributes[$col] = preg_replace('/[^.,\\s0-9]+/', '', $attributes[$col]); } } } foreach ($attributes as $name => $value) { $attributes[$name] = trim($value); if (empty($attributes[$name])) { unset($attributes[$name]); } } // True is set because import needs to be checked by the model. $model->setAttributes($attributes, $params['importType'] != 'Xls'); $this->_parseImportDates($model); try { if ($model->save()) { $this->afterImport($model, $attributes, $record); $summarylog->addSuccessful(); } else { $nameStr = !empty($record[0]) ? $record[0] : '"' . \GO::t('namelessItem') . '"'; $summarylog->addError($nameStr, implode("\n", $model->getValidationErrors())); } } catch (\Exception $e) { $summarylog->addError($record[0], $e->getMessage()); } // try{ // $model->save(); // $summarylog->addSuccessful(); // } // catch(\Exception $e){ // $summarylog->addError($record[0], $e->getMessage()); // } // $summarylog->add(); } } } else { //$summarylog->addError('NO FILE FOUND', 'There is no file found that can be imported!'); } return $summarylog; }