https://rt-wiki.bestpractical.com/api.php?action=feedcontributions&user=Barton&feedformat=atomRequest Tracker Wiki - User contributions [en]2024-03-28T18:49:22ZUser contributionsMediaWiki 1.37.2https://rt-wiki.bestpractical.com/index.php?title=GetSoftwareVersions&diff=26637GetSoftwareVersions2019-01-27T21:11:23Z<p>Barton: /* RT 4 */</p>
<hr />
<div>= Recent versions =<br />
<br />
In recent versions of RT, Visit the "Configuration" menu and then click on "Tools". RT has a "Running configuration" status page that lists off just about everything you need to know.<br />
<br />
= Old versions =<br />
<br />
Old versions of RT has no such functionality and you have to figure things out yourself.<br />
<br />
= RT =<br />
<br />
== RT 3 ==<br />
<br />
cat /opt/rt3/lib/RT.pm | grep VERSION<br />
<br />
== RT 4 ==<br />
<br />
perl -I/opt/rt4/lib -MRT -e'print "$RT::VERSION\n"';<br />
<br />
or<br />
<br />
grep VERSION /opt/rt4/lib/RT/Generated.pm<br />
<br />
= Configure =<br />
<br />
$ ./configure -V<br />
RT configure rt-4.4.3-60-g816ad9b68<br />
<br />
<br />
= Perl =<br />
<br />
perl -v<br />
<br />
<br />
More correct method for mod_perl users is print '$]' under mod_perl evironment, for eg:<br />
<br />
echo "<% $] %>" >/opt/rt3/local/html/test.html<br />
<br />
then in browser check [http://example.com/rt/test.html =]<br />
<br />
See [[ShowPerlVersion]]<br />
<br />
= <nowiki>!DBIx::!SearchBuilder</nowiki> =<br />
<br />
perl -MDBIx::SearchBuilder -e 'print $DBIx::SearchBuilder::VERSION;'<br />
<br />
= Apache =<br />
<br />
httpd -v<br />
<br />
= mod_perl =<br />
<br />
cat /usr/local/apache/logs/error_log | grep mod_perl | grep notice | tail -n 1<br />
<br />
= <nowiki>!MySQL</nowiki> =<br />
<br />
mysql -V<br />
<br />
= <nowiki>!PostgreSQL</nowiki> =<br />
<br />
postgres --version</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=GetSoftwareVersions&diff=26636GetSoftwareVersions2019-01-20T15:21:04Z<p>Barton: /* RT */ add perl -I/opt/rt4/lib -MRT -e'print "$RT::VERSION\n"';</p>
<hr />
<div>= Recent versions =<br />
<br />
In recent versions of RT, Visit the "Configuration" menu and then click on "Tools". RT has a "Running configuration" status page that lists off just about everything you need to know.<br />
<br />
= Old versions =<br />
<br />
Old versions of RT has no such functionality and you have to figure things out yourself.<br />
<br />
= RT =<br />
<br />
== RT 3 ==<br />
<br />
cat /opt/rt3/lib/RT.pm | grep VERSION<br />
<br />
== RT 4 ==<br />
<br />
perl -I/opt/rt4/lib -MRT -e'print "$RT::VERSION\n"';<br />
<br />
= Configure =<br />
<br />
$ ./configure -V<br />
RT configure rt-4.4.3-60-g816ad9b68<br />
<br />
<br />
= Perl =<br />
<br />
perl -v<br />
<br />
<br />
More correct method for mod_perl users is print '$]' under mod_perl evironment, for eg:<br />
<br />
echo "<% $] %>" >/opt/rt3/local/html/test.html<br />
<br />
then in browser check [http://example.com/rt/test.html =]<br />
<br />
See [[ShowPerlVersion]]<br />
<br />
= <nowiki>!DBIx::!SearchBuilder</nowiki> =<br />
<br />
perl -MDBIx::SearchBuilder -e 'print $DBIx::SearchBuilder::VERSION;'<br />
<br />
= Apache =<br />
<br />
httpd -v<br />
<br />
= mod_perl =<br />
<br />
cat /usr/local/apache/logs/error_log | grep mod_perl | grep notice | tail -n 1<br />
<br />
= <nowiki>!MySQL</nowiki> =<br />
<br />
mysql -V<br />
<br />
= <nowiki>!PostgreSQL</nowiki> =<br />
<br />
postgres --version</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=GetSoftwareVersions&diff=26635GetSoftwareVersions2019-01-20T15:04:03Z<p>Barton: Format 'RT' section.</p>
<hr />
<div>= Recent versions =<br />
<br />
In recent versions of RT, Visit the "Configuration" menu and then click on "Tools". RT has a "Running configuration" status page that lists off just about everything you need to know.<br />
<br />
= Old versions =<br />
<br />
Old versions of RT has no such functionality and you have to figure things out yourself.<br />
<br />
= RT =<br />
<br />
cat /opt/rt3/lib/RT.pm | grep VERSION<br />
<br />
= Configure =<br />
<br />
$ ./configure -V<br />
RT configure rt-4.4.3-60-g816ad9b68<br />
<br />
<br />
= Perl =<br />
<br />
perl -v<br />
<br />
<br />
More correct method for mod_perl users is print '$]' under mod_perl evironment, for eg:<br />
<br />
echo "<% $] %>" >/opt/rt3/local/html/test.html<br />
<br />
then in browser check [http://example.com/rt/test.html =]<br />
<br />
See [[ShowPerlVersion]]<br />
<br />
= <nowiki>!DBIx::!SearchBuilder</nowiki> =<br />
<br />
perl -MDBIx::SearchBuilder -e 'print $DBIx::SearchBuilder::VERSION;'<br />
<br />
= Apache =<br />
<br />
httpd -v<br />
<br />
= mod_perl =<br />
<br />
cat /usr/local/apache/logs/error_log | grep mod_perl | grep notice | tail -n 1<br />
<br />
= <nowiki>!MySQL</nowiki> =<br />
<br />
mysql -V<br />
<br />
= <nowiki>!PostgreSQL</nowiki> =<br />
<br />
postgres --version</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=GetSoftwareVersions&diff=26634GetSoftwareVersions2019-01-20T15:03:20Z<p>Barton: Add 'Configure', add code formatting.</p>
<hr />
<div>= Recent versions =<br />
<br />
In recent versions of RT, Visit the "Configuration" menu and then click on "Tools". RT has a "Running configuration" status page that lists off just about everything you need to know.<br />
<br />
= Old versions =<br />
<br />
Old versions of RT has no such functionality and you have to figure things out yourself.<br />
<br />
= RT =<br />
<br />
cat /opt/rt3/lib/RT.pm | grep VERSION<br />
<br />
= Configure =<br />
<br />
$ ./configure -V<br />
RT configure rt-4.4.3-60-g816ad9b68<br />
<br />
<br />
= Perl =<br />
<br />
perl -v<br />
<br />
<br />
More correct method for mod_perl users is print '$]' under mod_perl evironment, for eg:<br />
<br />
echo "<% $] %>" >/opt/rt3/local/html/test.html<br />
<br />
then in browser check [http://example.com/rt/test.html =]<br />
<br />
See [[ShowPerlVersion]]<br />
<br />
= <nowiki>!DBIx::!SearchBuilder</nowiki> =<br />
<br />
perl -MDBIx::SearchBuilder -e 'print $DBIx::SearchBuilder::VERSION;'<br />
<br />
= Apache =<br />
<br />
httpd -v<br />
<br />
= mod_perl =<br />
<br />
cat /usr/local/apache/logs/error_log | grep mod_perl | grep notice | tail -n 1<br />
<br />
= <nowiki>!MySQL</nowiki> =<br />
<br />
mysql -V<br />
<br />
= <nowiki>!PostgreSQL</nowiki> =<br />
<br />
postgres --version</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=CleanMasonCache&diff=26620CleanMasonCache2018-09-24T12:44:27Z<p>Barton: /* FreeBSD */ Improve code formatting</p>
<hr />
<div>Each file in the <code>share/html</code> directory is a mason component. Mason precompiles these files into Perl code and stores precompiled files in the cache dir. This feature speeds up processing as it doesn't need to recompile components each time. Also we can turn off checks on the original components if recompilation is required. Skipping such tests is done to speed up things more. RT uses both of these features. So when you change anything in the <code>share/html</code> or <code>local/html</code> directories, you '''must clear the mason cache''' to see changes. To clear the cache, run this command:<br />
<br />
shell&gt; rm -rf /opt/rt3/var/mason_data/obj/*<br />
<br />
'''NOTE''' Your path to RT may differ if you're using a packaged version of RT. Please, enter below paths for your OS distribution.<br />
== RedHat / CentOS ==<br />
'''Manual:'''<br />
<br />
Locate your RT install directory, in our case /usr/local/rt4<br />
rm -Rf /usr/local/rt4/var/mason_data/obj/*<br />
<br />
<br />
'''Scripted:'''<br />
<br />
<pre><br />
unset _response<br />
_rt=$(find /opt /usr -name mason_data)<br />
<br />
while [[ ( ${_response} != 'n' ) && ( ${_response} != 'N' ) && ( ${_response} != 'y' ) && ( ${_response} != 'Y' ) ]]; do<br />
read -p "Clearing mason cache in ${_rt}, continue? 'y/N': " _response<br />
done<br />
<br />
if [[ ( ${_response} == 'y' ) || ( ${_response} == 'Y' ) ]]; then<br />
{<br />
echo -n "Clearing mason cache in ${_rt}: "<br />
rm -rf ${_rt}/obj/*<br />
_status=${?}<br />
<br />
if [[ ${_status} == 0 ]]; then <br />
{<br />
echo "[ SUCCESS ]"<br />
}<br />
else<br />
{<br />
echo "[ FAIL ]"<br />
}<br />
fi<br />
}<br />
else<br />
{<br />
echo 'Exiting without clearning mason cache'<br />
}<br />
fi<br />
</pre><br />
<br />
== SUSE/openSUSE ==<br />
<br />
Assuming you have installed RT via the <code>request-tracker</code> package (as you should have), just run the <code>/usr/sbin/rt-clean-mason-cache</code> script as <code>root</code>.<br />
<br />
== FreeBSD ==<br />
<br />
In [[FreeBSD]], all third-party software is installed in /usr/local/, so the command would be:<br />
<br />
rm -rf /usr/local/rt3/var/mason_data/obj/*<br />
<br />
except for recent RT4 portbuild, where the RT var directory becomes /var/run/rt40<br />
<br />
So the command is<br />
<br />
rm -rf /var/run/rt40/mason_data/obj/*<br />
<br />
== Debian &amp; Ubuntu ==<br />
<br />
If you're using Debian packages then the filesystem location mentioned above is more likely to be /var/cache/request-tracker3.4/mason_data<br />
<br />
It may also be useful to know that [[DevelMode]] requires a Perl module called Module::Refresh, a package for which is not easily found. So if you're hacking on something and want to see the changes, you can clear the cache and restart Apache in one go like so:<br />
<br />
find /var/cache/request-tracker3.4/mason_data/ -type f -print0 | xargs -0 rm -f ; /etc/init.d/apache2 restart<br />
<br />
== For developers ==<br />
<br />
The [[DevelMode]] option allows you to avoid this step, but note that you don't want to use this option in production environment.</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=CleanMasonCache&diff=26619CleanMasonCache2018-09-24T12:43:17Z<p>Barton: /* Debian &amp; Ubuntu */ improve code formatting</p>
<hr />
<div>Each file in the <code>share/html</code> directory is a mason component. Mason precompiles these files into Perl code and stores precompiled files in the cache dir. This feature speeds up processing as it doesn't need to recompile components each time. Also we can turn off checks on the original components if recompilation is required. Skipping such tests is done to speed up things more. RT uses both of these features. So when you change anything in the <code>share/html</code> or <code>local/html</code> directories, you '''must clear the mason cache''' to see changes. To clear the cache, run this command:<br />
<br />
shell&gt; rm -rf /opt/rt3/var/mason_data/obj/*<br />
<br />
'''NOTE''' Your path to RT may differ if you're using a packaged version of RT. Please, enter below paths for your OS distribution.<br />
== RedHat / CentOS ==<br />
'''Manual:'''<br />
<br />
Locate your RT install directory, in our case /usr/local/rt4<br />
rm -Rf /usr/local/rt4/var/mason_data/obj/*<br />
<br />
<br />
'''Scripted:'''<br />
<br />
<pre><br />
unset _response<br />
_rt=$(find /opt /usr -name mason_data)<br />
<br />
while [[ ( ${_response} != 'n' ) && ( ${_response} != 'N' ) && ( ${_response} != 'y' ) && ( ${_response} != 'Y' ) ]]; do<br />
read -p "Clearing mason cache in ${_rt}, continue? 'y/N': " _response<br />
done<br />
<br />
if [[ ( ${_response} == 'y' ) || ( ${_response} == 'Y' ) ]]; then<br />
{<br />
echo -n "Clearing mason cache in ${_rt}: "<br />
rm -rf ${_rt}/obj/*<br />
_status=${?}<br />
<br />
if [[ ${_status} == 0 ]]; then <br />
{<br />
echo "[ SUCCESS ]"<br />
}<br />
else<br />
{<br />
echo "[ FAIL ]"<br />
}<br />
fi<br />
}<br />
else<br />
{<br />
echo 'Exiting without clearning mason cache'<br />
}<br />
fi<br />
</pre><br />
<br />
== SUSE/openSUSE ==<br />
<br />
Assuming you have installed RT via the <code>request-tracker</code> package (as you should have), just run the <code>/usr/sbin/rt-clean-mason-cache</code> script as <code>root</code>.<br />
<br />
== FreeBSD ==<br />
<br />
In [[FreeBSD]], all third-party software is installed in /usr/local/, so the command would be:<br />
<br />
rm -rf /usr/local/rt3/var/mason_data/obj/*<br />
<br />
except for recent RT4 portbuild, where the RT var directory becomes /var/run/rt40<br />
<br />
So the command is rm -rf /var/run/rt40/mason_data/obj/*<br />
<br />
== Debian &amp; Ubuntu ==<br />
<br />
If you're using Debian packages then the filesystem location mentioned above is more likely to be /var/cache/request-tracker3.4/mason_data<br />
<br />
It may also be useful to know that [[DevelMode]] requires a Perl module called Module::Refresh, a package for which is not easily found. So if you're hacking on something and want to see the changes, you can clear the cache and restart Apache in one go like so:<br />
<br />
find /var/cache/request-tracker3.4/mason_data/ -type f -print0 | xargs -0 rm -f ; /etc/init.d/apache2 restart<br />
<br />
== For developers ==<br />
<br />
The [[DevelMode]] option allows you to avoid this step, but note that you don't want to use this option in production environment.</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=CleanMasonCache&diff=26618CleanMasonCache2018-09-24T12:42:04Z<p>Barton: /* RedHat / CentOS */ improve code formatting</p>
<hr />
<div>Each file in the <code>share/html</code> directory is a mason component. Mason precompiles these files into Perl code and stores precompiled files in the cache dir. This feature speeds up processing as it doesn't need to recompile components each time. Also we can turn off checks on the original components if recompilation is required. Skipping such tests is done to speed up things more. RT uses both of these features. So when you change anything in the <code>share/html</code> or <code>local/html</code> directories, you '''must clear the mason cache''' to see changes. To clear the cache, run this command:<br />
<br />
shell&gt; rm -rf /opt/rt3/var/mason_data/obj/*<br />
<br />
'''NOTE''' Your path to RT may differ if you're using a packaged version of RT. Please, enter below paths for your OS distribution.<br />
== RedHat / CentOS ==<br />
'''Manual:'''<br />
<br />
Locate your RT install directory, in our case /usr/local/rt4<br />
rm -Rf /usr/local/rt4/var/mason_data/obj/*<br />
<br />
<br />
'''Scripted:'''<br />
<br />
<pre><br />
unset _response<br />
_rt=$(find /opt /usr -name mason_data)<br />
<br />
while [[ ( ${_response} != 'n' ) && ( ${_response} != 'N' ) && ( ${_response} != 'y' ) && ( ${_response} != 'Y' ) ]]; do<br />
read -p "Clearing mason cache in ${_rt}, continue? 'y/N': " _response<br />
done<br />
<br />
if [[ ( ${_response} == 'y' ) || ( ${_response} == 'Y' ) ]]; then<br />
{<br />
echo -n "Clearing mason cache in ${_rt}: "<br />
rm -rf ${_rt}/obj/*<br />
_status=${?}<br />
<br />
if [[ ${_status} == 0 ]]; then <br />
{<br />
echo "[ SUCCESS ]"<br />
}<br />
else<br />
{<br />
echo "[ FAIL ]"<br />
}<br />
fi<br />
}<br />
else<br />
{<br />
echo 'Exiting without clearning mason cache'<br />
}<br />
fi<br />
</pre><br />
<br />
== SUSE/openSUSE ==<br />
<br />
Assuming you have installed RT via the <code>request-tracker</code> package (as you should have), just run the <code>/usr/sbin/rt-clean-mason-cache</code> script as <code>root</code>.<br />
<br />
== FreeBSD ==<br />
<br />
In [[FreeBSD]], all third-party software is installed in /usr/local/, so the command would be:<br />
<br />
rm -rf /usr/local/rt3/var/mason_data/obj/*<br />
<br />
except for recent RT4 portbuild, where the RT var directory becomes /var/run/rt40<br />
<br />
So the command is rm -rf /var/run/rt40/mason_data/obj/*<br />
<br />
== Debian &amp; Ubuntu ==<br />
<br />
If you're using Debian packages then the filesystem location mentioned above is more likely to be /var/cache/request-tracker3.4/mason_data<br />
<br />
It may also be useful to know that [[DevelMode]] requires a Perl module called Module::Refresh, a package for which is not easily found. So if you're hacking on something and want to see the changes, you can clear the cache and restart Apache in one go like so:<br />
<br />
find /var/cache/request-tracker3.4/mason_data/ -type f -print0 | xargs -0 rm -f ; /etc/init.d/apache2 restart<br />
<br />
== For developers ==<br />
<br />
The [[DevelMode]] option allows you to avoid this step, but note that you don't want to use this option in production environment.</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=CopyContentToCF&diff=26531CopyContentToCF2017-10-13T14:14:38Z<p>Barton: /* Custom action code */</p>
<hr />
<div>= Overview =<br />
<br />
This is a work around for the fact that *quote folding* is always active, regardless of whether ticket is just being created. [See my post to the forums about this issue](https://forum.bestpractical.com/t/change-quoting-in-forwarded-tickets/32100). Keith Creasy suggested copying the content of the initial transaction into a custom field called <tt>Problem</tt>. This also has the advantage that the <tt>Problem</tt> CF can be edited later, as the ticket evolves, which makes it a useful repository for information that you want to see at the top of the ticket.<br />
<br />
= Basics =<br />
<br />
* Conditon: *On Create*<br />
* Action: *User Defined*<br />
* Template: *Blank*<br />
<br />
= Custom action preparation code =<br />
<br />
<syntaxhighlight lang="perl"><br />
1;<br />
</syntaxhighlight><br />
<br />
= Custom action code =<br />
<br />
<syntaxhighlight lang="perl"><br />
my $Ticket = $self->TicketObj;<br />
my $Transaction = $self->TransactionObj;<br />
my $CF = RT::CustomField->new( $RT::SystemUser );<br />
<br />
$CF->LoadByNameAndQueue( Name => 'Problem', Queue => $Ticket->Queue );<br />
<br />
$CF->AddValueForObject( <br />
Object => $Ticket, Content => $Transaction->Content <br />
);<br />
</syntaxhighlight></div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=CopyContentToCF&diff=26522CopyContentToCF2017-09-11T00:05:23Z<p>Barton: Created page with "= Overview = This is a work around for the fact that *quote folding* is always active, regardless of whether ticket is just being created. [See my post to the forums about th..."</p>
<hr />
<div>= Overview =<br />
<br />
This is a work around for the fact that *quote folding* is always active, regardless of whether ticket is just being created. [See my post to the forums about this issue](https://forum.bestpractical.com/t/change-quoting-in-forwarded-tickets/32100). Keith Creasy suggested copying the content of the initial transaction into a custom field called <tt>Problem</tt>. This also has the advantage that the <tt>Problem</tt> CF can be edited later, as the ticket evolves, which makes it a useful repository for information that you want to see at the top of the ticket.<br />
<br />
= Basics =<br />
<br />
* Conditon: *On Create*<br />
* Action: *User Defined*<br />
* Template: *Blank*<br />
<br />
= Custom action preparation code =<br />
<br />
<syntaxhighlight lang="perl"><br />
1;<br />
</syntaxhighlight><br />
<br />
= Custom action code =<br />
<br />
<syntaxhighlight lang="perl"><br />
my $Ticket = $self->TicketObj;<br />
my $Transaction = $self->TransactionObj;<br />
my $CF = RT::CustomField->new( $RT::SystemUser );<br />
<br />
$CF->LoadByNameAndQueue( Name => 'Problem', Queue => $Ticket->Queue );<br />
<br />
$CF->AddValueForObject( Object => $Ticket, Content => $Transaction->Content );<br />
</syntaxhighlight></div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=Contributions&diff=26521Contributions2017-09-10T23:30:17Z<p>Barton: </p>
<hr />
<div>= Contributions to RT =<br />
<br />
Contains info about software that third parties have contributed to RT. If you know of a contribution or enhancement that is not in this list, please add to the best section possible below, in alphabetical order. Also include notes about the RT versions tested.<br />
<br />
You may also want to check the [[Documentation]] page because many articles there describe how to add features that RT does not have by default.<br />
<br />
Packages that have their own installer have been moved to [[Extensions]].<br />
<br />
See Also the outdated [[Patches]], whose content should be moved to the appropriate subsections below.<br />
<br />
== Coping with Spam ==<br />
<br />
The techniques for dealing with spam span the divisions below and have been collected in a single place for easy review. Please see [[SpamFiltering]], limiting additions to tricks that differ significantly from the existing material for conciseness.<br />
<br />
== ScripConditions ==<br />
<br />
Custom [[Condition]]s. Doesn't matter if it's module or text to fill into "user defined condition" block in the WebUI, all live here.<br />
<br />
'''<nowiki>*Please</nowiki>'''*, start wiki page names with "On" prefix if you don't want to add condition into [[CustomConditionSnippets]].<br />
<br />
* [[CustomConditionSnippets]] - '''very big''' and organized list of simple conditions<br />
<br />
* [[AnyTransactionSource]];<br />
* [[AnyReminderTransaction]] - a scrip condition which triggers on all reminder transactions;<br />
* [[MuteResolve]] - let resolver choose not to send email on resolve;<br />
* [[MuteResolve Redux]] - alternate version of MuteResolve that uses a status code and custom field to avoid some problems;<br />
* [[NotResolved]] - a scrip condition to detect all ticket that aren't marked resolved;<br />
* [[On Correspond Notify AdminCcs if Not Owned|OnCorrespondNotifyAdminCcsNotOwned]] - Notifies AdminCc only if ticket is unowned<br />
* [[OnCreateAutoReplyException]] - a scrip condition that will send [[AutoReply]] emails to users except for those in the execption list;<br />
* [[OnCreateCheckCF]] - check presence of a mandatory cf on ticket creation;<br />
* [[OnCreateFromEmail]] - scrip condition that will send [[AutoReply]] emails to users only when a ticket is opened via email;<br />
* [[OnCreationOfApprovalTicket]] - a scrip condition that checks if you are creating a new approval ticket<br />
* [[OnCreatePageOffHours]] - scrip condition that will send email via the [[SendEmailAction]] scrip to and external account. This scrip has an additional condition where it is checking if the request is coming from a specific user or system.<br />
* [[OnCreateSetUserDetails]] - parse vCards for user information.<br />
* [[OnCustomFieldValueChange]] - this condition matches when [[CustomField]] value is changed;<br />
* [[OnMaxPriority]] - check if ticket hits maximal priority (used with priority escalation)<br />
* [[OnMerge]] - a scrip condition that triggers on ticket merges;<br />
* [[OnResolveOnce]] - a scrip condition that matches when a ticket is resolved but only if the ticket was not resolved before;<br />
* [[OnStatusChange]] - using RT's condition 'On Resolve' to trigger other conditions<br />
* [[OnStealEnhanced]] - small enhancement to the [[OnSteal]] condition in "RT Essentials".<br />
* [[OnTimeEstimated]] - when the time Time Estimated fields is set<br />
* [[OnToOrCC]] - when a request is sent to a particular mailbox<br />
* [[OnWatcherChange]] - a scrip condition to detect when a ticket watcher is added or deleted.<br />
* [[OnWebCorrespond]] - determines if a reply is from an incoming email message or from the web interface.<br />
* [[ReplyBasedUponContent]] - a scrip to reply to an email based upon its content<br />
* [[ReplyToResolved]] - a scrip condition to detect all ticket that are marked resolved;<br />
* [[ShowDashboardTabs]] - add dashboards to the personal quickbar<br />
* [[TicketIDMatches]].pm - a condition which triggers only one ticket by id;<br />
* [[UntouchedInHours]] - scrip condition that checks if a ticket's LastUpdate is more than the specified number of hours;<br />
* [[OnCorrespondOpenUnlessResolved]] - condition to stop RT re-opening resolved tickets when the user replies to them by email;<br />
* [[NoReplyAddress]] - Use a "no reply" RT email address that posts comments as a Reply/Correspondence (so they can see it in web UI), but does not send email to Requestors<br />
<br />
== ScripActions ==<br />
<br />
Nice custom [[ScripAction]]s that makes your life easier.<br />
<br />
* [[AddAdminCc]] - Add an [[AdminCc]] to tickets for a specific queue, or for queue change.<br />
* [[AddAdminCcAndChangeQueue]] - Add an [[AdminCc]] to a ticket, and move the ticket to a queue.<br />
* [[AddSquelchedCc]] - Add group members as Cc to give them access to tickets but without email notifications.<br />
* [[AddRefersToOnEqualCustomField]] - Create [[RefersTo]] links to tickets with same custom field value<br />
* [[AddRequestor]] - Allow some accounts to view a ticket without adding by hand some requestors.<br />
* [[AddWatcherPerTicket]] - Add a watcher to a specific ticket (e.g. when certain conditions are met, such as high urgency)<br />
* [[AddWatchersOnCorrespond]] - Add Actor &amp; other Cc'd people to ticket on any Correspondence (complement to using [[ParseNewMessageForTicketCcs]] to add people on ticket creation).<br />
* [[LoopIn]] - Similar to [[AddWatchersOnCorrespond]], but with some additional security and rules to prevent random people from getting added to existing tickets.<br />
* [[AutomaticCustomFieldValue]] - set CF value by requestor's email address.<br />
* [[AutoCcOwner]] - Add the owner as an [[AdminCc]]<br />
* [[AutoCcLastOwner]] - When the owner is changed, automatically add the previous owner to the Cc list.<br />
* [[AutoChangeQueue]] - Change queue if a specific group member take a ticket<br />
* [[AutoCloseOnNagiosRecoveryMessages]] - Automatically merges and closes a ticket based on the creation of another ticket, in this case, of a nagios generated RECOVERY e-mail<br />
* [[AutoSetOwner]] - how to automatically set owner on resolution<br />
* [[AutoSetOwnerIfAdminCc]] - Automatically set ticket owner to an [[AdminCc]]<br />
* [[AutoSetOwnerFromCC]] - how to automatically set owner from Cc<br />
* [[BounceMerge]] - Merge a Mail Bounce into the original Ticket<br />
* [[CcManagers]] - Add the manager subgroup of the ticket creator as Cc, useful when managing departments as groups (as [[Rights|rights]] suggests).<br />
* [[CopyContentToCF]] - When called 'On Create' will copy <tt>$Transaction->Content</tt> to the custom field <tt>Problem</tt>.<br />
* [[CreatePriorityBasedOnCustomFieldValues]] - Automatically set the Priority based on Ticket Urgency and Impact.<br />
* [[DefaultCustomFieldValue]] - set default CF value.<br />
* [[DivideTicketIntoSubtasks]] - auto-creates new tickets for each subtask in a bulleted list<br />
* [[DueDateinBusinessHours]] - scrip action that sets short-term ticket due dates to coincide with business hours<br />
* [[EscalateTicketOnAction]] - increment the priority of a ticket whenever a certain action is taken<br />
* [[ExtractCustomFieldValues]] - set [[CustomField]] with arbitrary data extracted from a ticket using a simple template<br />
* [[ForkIntoNewTicket]] - a scrip action to copy response/comment ticket to another ticket<br />
* [[JumpToFrontPageOnTicketResolve]] - Admonish me if you wish, but on resolve of a ticket this scrip will redirect your browser to a new URL of your choosing.<br />
* [[NotifyNonRecipients]] - notify recipients unless they were already cc'd on the mail<br />
* [[OnCreateSetDeptHeadCc]] - On create in the case that [[CustomField]].Department = 'Foo' then add group 'Head Foo' as a Cc<br />
* [[OnCreateAddGroupCc]] - On create from Requestor email that matches a regex, add members of arbitrary group to CC list while making sure not to add anyone already associated with the ticket<br />
* [[OnOwnershipSquelchMailtoQueueWatchers]] - When a ticket's owner changes from "Nobody" to a regular user, stop sending mail to people who are just Queue Watchers.<br />
* [[OnQueueChangeFixReminders]] - Tickets lose reminders when they are moved between queues. This scrip fixes that<br />
* [[OnQueueChangeResetPriorityAndDueDate ]] - Reset priorities and due date when moving a ticket to another queue.<br />
* [[OpenTicketOnAllMemberResolve]]<br />
* [[OpenDependantsOnResolve]]<br />
* [[RemoteControlLimeSurvey2]] - new Version of the old [[RemoteControlLimeSurvey]] - Scrip action to trigger [[LimeSurvey]] to add a token to a given survey.<br />
* [[ResolveTicket]]<br />
* [[SendEmailAction]] - sends an alert to someone not specified in the ticket<br />
* [[SendHTMLEmail]] - modification of RT::Action::[[SendEmail]] for sending mails with Content-Type: text/html<br />
* [[SendNagiosAlert]] - Send an alert to Nagios if a new or open ticket exists in any defined queues.<br />
* [[SendAlarmPointEvent]] - Send an event to alarm point to invoke SMS/Voice/E-mail alerts<br />
* [[SetActiveOnCustomerReply]] - detects if a ticket is set to a certain status and changes that status if someone other than the ticket owner replies.<br />
* [[SetCorresponderAsCC]] - Add anyone who correspondes on a ticket to CC - for the lazy users.<br />
* [[SetOwnerAndQueueBySubject]] - Set queue and owner when the subject matches a regex<br />
* [[SetTicketPropertiesViaMail]] - scrip action that allow you to set status, owner and etc via email<br />
* [[SetTimeWorkedAutomatically]] - scrip action that updates automatically the Time Worked field on the Ticket<br />
* [[SpamScore2Priority]] - Expose message spam score as priority for review<br />
<br />
== Template parts ==<br />
<br />
Code that you can put into your mail [[Template]]s, [[Template]] page has also some code snippets.<br />
<br />
* [[AddAttachmentLinksToMail]] - adds links on file attachments that ticket has<br />
* [[AddCustomFieldsValuesToMail]] - puts all [[CustomField]]s values into mail<br />
* [[AddCustomFieldstoTemplates]] - extracting just one or more [[CustomField]]s, without recalling the entire set<br />
* [[AddTicketHistoryToMail]] - complex template that adds ticket's history<br />
* [[AddQueueNameToMailHeaders]] - add the relevent queue name to mail sent<br />
* [[AddLastCommentToMail]]<br />
* [[AddRichTextEditorToCustomField]] - add CKEditor to a [[CustomField]]s textarea values<br />
* [[AutoreplyOrCorrespondence]] - if creator is not requestor use Corresondence instead of Autoreply<br />
* [[EmailGroup]] - email an RT [[Group]]<br />
* [[ForkTemplate]] - send a range of customized responses without hard-coding variants.<br />
* [[ForwardFirstMessage]] - re-send the first message (i.e. ticket creation message)<br />
* [[MailingListIntegration]] - Scrip + Template to optionally subscribe requestors to a listserv.<br />
* [[MultipleOutgoingEmailAddresses]]<br />
* [[UseActorAsSender]]<br />
* [[X-Priority]] - Maps RT priority field to email priority header.<br />
<br />
== Callbacks ==<br />
<br />
Callbacks are an easy way to [[CleanlyCustomizeRT]]<br />
<br />
* [[CloningQueues]] - Add user functionality to clone existing queues including templates, scrips, privileges and custom fields during queue creation<br />
* [[CreateChildTicket]] - Add a button to the Ticket display to create a child ticket in another queue<br />
* [[HideTransactions]] - hide messages from a history view<br />
* [[ModifyQuery]] -Change default simple search behavior to in/ex-clude closed tickets, etc.<br />
* [[MakeClicky:Fedex]] - Make a link to Fedex tracking website whenever phrase looks like a tracking number<br />
* [[QuickResolveandQuickReject]] - Create two actions in Display page which allow you to reject or resolve the ticket without no comments.<br />
* [[MailtoLinksFromTransactions]] - Create mailto-inks at the top of transactions<br />
* [[TwoColumnTicketLayout]] - Display a ticket's history and metadata side by side<br />
* [[AutoRequestorTicketSearch]] - Automatically search for requestor's last updated tickets on creation page<br />
* [[NewTicketsAlert]] - Display a messagebox on My RT listing new tickets and add new ticket count to page title<br />
<br />
== Extensions ==<br />
<br />
Patches, [[Overlays]], Mason components, configuration tools and so on. These extensions are unlikely to become RT core package.<br />
<br />
Packages that have their own installer have been moved to [[Extensions]] - Below are code bits too small/experimental/etc. to warrant a standalone package:<br />
<br />
* [[AutomaticImageResize]] -- automatically scale images that are displayed inline in your ticket history<br />
* [[AutoRedirectToSelfService]] - automatically redirect your users to Self Service if they don't have "own ticket" permissions;<br />
* [[BasicVsAdvancedInterface]] - allow privileged users to choose between the [[SelfService]] and RT at a Glance interfaces<br />
* [[BetterPerformanceWithFullText]] - tweak to improve full text search in Postgres (and a note about Oracle).<br />
* [[CalendarWidget]] - add a the dynarch.com jscalendar widget to pick dates<br />
* [[CannedReplies]] - provides drop-down list of templates that can be included in a ticket reply<br />
* [[ColorizedLinks]] - colorizing list of Ticket Links depends on it's status<br />
* [[ConvertMultiSelectToCheckboxes]] - converts the multiselect customfield into a checkbox interface<br />
* [[CreateGroupAndAddMembers]] - an overylay that grants [[AdminGroupMembership]] when a user creates a group<br />
* [[CustomFieldRightsWithoutSeeQueue]] - for a custom ticket creation form that includes the custom fields and you don't want to turn on the [[SeeQueue]] right;<br />
* [[DisplayCustomFieldsInTicketSearch]];<br />
* [[DisplayCustomFieldsInUserPrefs]] - add user-based custom fields to User/Prefs.html<br />
* [[DisplayCustomFieldsOnTicketUpdatePage]] - Make a ticket's custom fields visible when updating or resolving a ticket.<br />
* [[EditCustomFieldsOnUpdate]] - edit custom fields on update, reply, comment...;<br />
* [[ForwardWithMessage]] - forward a transaction or ticket WITH a message for the recipient<br />
* [[GroupMembershipCheck]] - snippet that can be included in a custom form if you want to limit the display of some things to a specific group;<br />
* [[HideTransactions]] - hide messages from a history view<br />
* [[HomePageSavedSearches]] - display lists of saved searches on the RT home page;<br />
* [[HTML5Charts]] - eye candy with jqplot;<br />
* [[ImportCustomFieldValues]] - Fills custom field data from external source;<br />
* [[LdapSummary]] - Several authentication and user creation techniques<br />
* [[MaintenanceMode]] - a quick and dirty way to shut down your site temporarily<br />
* [[MandatorySubject]] - make a ticket's Subject mandatory using [[JavaScript]]<br />
* [[MoreAboutPrivilegedUsers]] - show the More About box for privileged users<br />
* [[MoveRTName]] - Move the $rtname to the end of a subject line<br />
* [[MultipleSubjectTokens]] - Change subject token dependend on queue name<br />
* [[PasswordReset]] - show password reset on login<br />
* [[PersistentSessions]] - Making users' sessions persistent<br />
* [[PopUpAlert]] - Send Reply instead of Comment<br />
* [[QuickTicket]] - quickly create a ticket on homepage with custom fields and status<br />
* [[Extension - Queue Change On Update]] - This is a plugin which adds a callback to RT with the result that you add a Queue change dropdown box to the ticket update page (comment/reply page). Very handy for proper ticket transport between Queue's, especially whena Queue represents a department.<br />
* [[Rich Text Custom Fields]] - convert wiki text custom fields into rich text custom fields<br />
* [[ResolveSendsReply]] - change the "Resolve" link to reply instead of comment by default<br />
* [[SelectRequestor]] - allow user to select requestor from drop down lists instead of typing email address;<br />
* [[SelectDefaultQueue]] - Using a user-based custom field, cause all queue name drop down lists to autopick that queue<br />
* [[SendEmail]] - lets template send an e-mail without adding RT ticket info to subject line<br />
* [[ShortcutPopupMenuScript]] - Javascript based popup menu of useful actions for ticket list<br />
* [[SideBySideTicketScreen]] - ticket update screen that shows ticket history "side-by-side" with ticket details.<br />
* [[SignatureToTheTop]] - Insert user's signature to the top of the message, not to the bottom as default<br />
* [[SimpleSearchExcludeResolved]] - exclude resolved and rejected tickets from simple search results<br />
* [[ShowStatusInColor]] - show status (or priority) in Color in Search screens;<br />
* [[ShowPerQueueInstructions]]<br />
* [[SpawnChildTicket]] - spawn a child ticket in a given queue list;<br />
* [[SpatialRT]] - Plot tickets on a map. More of a recipe than a full solution but could be expanded.<br />
* [http://wiki.bestpractical.com/view/Spreadsheet+RequestorDetails Spreadsheet+RequestorDetails] - Creates a Spreadsheet link which includes some requestor details if the user has the rights to see them (Global ACL [[AdminUsers]])<br />
* [[SpreadsheetDisplayedFields]] - download just the displayed search result fields into a spreadsheet;<br />
* [[StockAnswers]] - insert predefined templates into replies - now with a template editor;<br />
* [[SuppressOutgoingMail]] - optionally turn off outgoing mail<br />
* [[TextBasedPriorities]] - use <code>Normal, High, Emergency...</code> for priority value instead of numbers;<br />
* [[TicketsPerQueue]] - Display X unowned tickets per queue a user has rights to<br />
* [[TimeWorked]] - Display a report with total time worked per queue/per user<br />
* [[TimeWorkedReport]] - Display a report with total time worked per user per ticket for one or more queues.<br />
* [[TimelineStartDue]] - Modify Timeline package to display tickets using the Start and Due date<br />
* [[UpdateTimeLeft]] - update Time Left -field from <code>Update.html</code> (/reply, comment/)<br />
* [[ViewMyRequests]] - mod to [[SelfService]] that allows requestors to see ticket summaries, and details of their own tickets;<br />
* [[WhoHasRightsToWhat]] - a mason component that makes it easier to understand your complex rights setup.<br />
* [[WatcherSummary]] - a mason component that gives you an overview of tickets where a user is listed as a watcher.<br />
* [[LockLessSessionsMySQL]] - a new version of Sessions which works in no-locking mode<br />
<br />
== External utils ==<br />
<br />
Various standalone utilities.<br />
<br />
* [[backupRT]] - Run a quick backup of RT files (Debian)<br />
* [[backupRTDB]] - RT Database Backup Script (Debian)<br />
* [http://nextup.cz/bestpractical-rt-widget/ BestPracticalRT Mac OSX Widget] - simple configurable OSX widget for quick posting tickets<br />
* [http://search.cpan.org/dist/Bot-BasicBot-Pluggable-Module-RT Bot::BasicBot::Pluggable::Module::RT] - an IRC Bot module that allows full querying of RT tickets from an IRC session. It can do as much as [http://search.cpan.org/dist/RT-Client-REST/ RT::Client::REST] can.<br />
* [[CleanupSessions]] - Clean up old database sessions<br />
* [[CloseAll]] - Close all TT in a queue<br />
* [[ConvertLegacyToRt]] - Converts a Legacy Flat File to RT Tickets.<br />
* [[delete-transaction]] - [http://download.bestpractical.com/pub/rt/contrib/3.0/Other/Censorware/delete-transaction Original version] was old, poured out errors and didn;t work well on 3.8. This one is fixed.<br />
* [[DenormalizedViewsForReporting]] - Several views to allow SQL reporting outside of RT.<br />
* [https://github.com/botsie/dirt Dirt] - A web application that provides kanban boards, scrum taskboards, graphical and tabluar reports on top of RT. <br />
* Email reminders<br />
** [[DueDateRemindersByEmail]] - A script (to be run daily) that sends email notifications for expired tickets to owners and Queues/Tickets [[AdminCC]]<br />
** [http://www.cs.kent.ac.uk/people/staff/tdb/rt3/ rt-remind] - Stick this in your crontab to send out reminders about open tickets.<br />
** [[rtReminderMails]] - Cronscript that sends mails about reminders that are due in the next two days to the ticket and reminder owners.<br />
** [[rtUnifiedreminder]] - All the other reminder scripts are based on [[StartDate]], [[DueDate]] or Priority but not all organizations make use of those fields. Also, all the other scripts only send plaintext email to the ticket owner. This script sends one HTML mail (so you can click the tickets and links to RT searches) that lists all tickets that seem to be getting too old without being touched. "Too old" is based on [[LastUpdated]] field, with the amount of time configurable for New, Open and Stalled tickets.<br />
** [[rt-askForFeedback]] - This Script bases on the above "[[DueDateRemindersByEmail]]" and got modified in the way, that it sends Mails to customers other than to administrators and Ticket-Owner. You will be able to "remind" customer to get back to you with a reply if the ticket is in "stalled"-State. If there is no response within a time of "x", you can autoclose the ticket.<br />
* [http://www.bestpractical.com/pub/rt/contrib/3.0/Other/F2Wcvs-to-rt-3.0 F2Wcvs-to-rt] - Tool to help converting from the [http://f2w.sourceforge.net/ F2W] helpdesk system to RT<br />
* [http://mit.edu/alexmv/Public/graph-mason-deps graph-mason-deps] uses [http://www.graphviz.org/ GraphViz] to create a graph of which components call each other<br />
* [[html2mime]] - small perl script used to create a text/plain part from 100% html messages<br />
* [http://pthbb.org/software/manual/mailfilter mailfilter] - spam checking and more<br />
* [[Mbox2Rt]] - import a unix-style mailbox into RT<br />
* [[ProcmailRecipes]] - procmail recipes used for email filtering<br />
* [http://www.dmo.ca/projects/hacks/RT/RT.bm RT.bm] is a plugin for [http://www.mozilla.org/projects/mozbot/ mozbot] that allows some minimal querying of RT tickets from an IRC session.<br />
* [http://www.bestpractical.com/pub/rt/contrib/3.0/Other/rtadduser rt-adduser] ([http://www.bestpractical.com/pub/rt/contrib/3.0/Other/rtadduser.README docs]) - command line tool to add RT users.<br />
* [[Rt-auth-user|rt-auth-user]] - perl script for authenticating a user against RT (both local and external sources through [[ExternalAuth]] )<br />
* [http://mimosaid.007sites.com/rt-batch-add-users.txt rt-batch-add-users] - command line tool to add a batch of RT users based on data of a csv file.<br />
* [rt-batch-stats [[RT3BatchStats]]] - Command Line or batch statistics.<br />
* [[RtBounceHandler]] - scan bounce email for ticket details, then post essense of bounce info to that ticket.<br />
* [http://www.cpan.org/authors/id/A/AH/AHARRISON/scripts/rt-class-map-1.3.pl rt-class-map-1.3-pl] - Show methods available to specific RT objects.<br />
* [http://www.bestpractical.com/pub/rt/contrib/3.0/rt-cvsgate.txt rt-cvsgate] ([http://www.bestpractical.com/pub/rt/contrib/3.0/rt-cvsgate.README docs]) - cvs integration for request tracker.<br />
* [http://www.cs.kent.ac.uk/people/staff/tdb/rt3/ rt-escalate] ([[ConfigureEscalation]]) - stick this in your crontab to escalate priority on tickets automatically<br />
* [[RTLogins]] - simple php script that creates a login report ("Who's using RT?")<br />
* [http://wiki.bestpractical.com/view/rt_logins_email2ldap rt_logins_email2ldap] - script to convert email usernames to LDAP/Active Directory usernames<br />
* [[rt-google-charts]] - produce google charts for queue statistics<br />
* [http://www.bestpractical.com/pub/rt/contrib/3.0/Conversion/rt3-on-pg-to-mysql rt-on-pg-to-mysql] - Convert your rt database from postgres to mysql.<br />
* [http://shellscripts.org/project/rtqueues rt-queues] Shellscript called from procmail to sort E-Mails to the correct queue. Parses incoming mails and based on addresses in To: and CC: fields automatically sorts mails to the correct queue. This makes changing your MTA configuration for every new queue obsolete.<br />
* [[RtTalkToSelf]] - a mail filter script that allows a single RT instance to have one ticket as the "external requestor" of another.<br />
* [[scan-and-set]] - sample perl script to all the text attachments of open tickets for a text string and set a custom field with the result.<br />
* [http://www.jeconley.com/pub/rt/statdump statdump/statcron] - script and cronjob to generate RT management reports. The original URL is defunct, but a patched version of the scripts are still in [http://www.nabble.com/Patched-statdump-statcron-scripts-td2264154.html listarchives]. An updated version that fixed [[AverageTickets]] calcs and CURDATE selection used to be available at http://www.lei.net.au/stats.tgz.<br />
* [[CountTickets]] - a BASH script to count tickets in a [[MySQL]] db.<br />
* [[ShredderControl]] - a BASH script to shred tickets using [[RTx]]-Shredder.<br />
* [[MigrateBugzillaToRT]] - Migrate a Bugzilla instance cleanly to RT<br />
* [[IntegrateSphinx]] - How to integrate the Sphinx full-text search engine into RT<br />
* [[SendingCommentsDirectlyToATicketWithExim4]] - How to configure exim4 to send comments to tickets based on ticket ID and custom field values<br />
* [[rt-clonequeue]] - a perl script used to create a new queue using an existing one as a template (copying its custom fields, permissions, templates and scrips but not its tickets).<br />
<br />
<br />
<br />
=== Browser Tools ===<br />
<br />
* [[AutomaticTextareaAutosave]] - Firefox + Windows only<br />
* Integrated Browser Search - Add a custom search engine for RT system to your modern browser with [[OpenSearchPluginForRT]]. See also [[SearchRTFromFirefox]].<br />
* [[RTKeyboardShortcut]] - Firefox + Greasmonky script (can be added to an installation)<br />
<br />
== Database Queries ==<br />
<br />
* [[QueryResolvedByUser]]<br />
<br />
== Other ==<br />
<br />
* [http://www.cs.mu.oz.au/systems/rt.html Department of Computer Science and Software Engineering, The University of Melbourne's RT page]<br />
* [http://page.mi.fu-berlin.de/~pape/rt3screenshots/ Dirk Pape's RT page] (Fixed "Fork" tarball link, I hope it is the right Version.)<br />
* [http://web.mit.edu/tooltime/ MIT IS&amp;T RT page]<br />
* [http://www.usit.uio.no/it/rt/modifications/ University of Oslo's RT page]<br />
* [http://www.cs.kent.ac.uk/people/staff/tdb/rt3/ University of Kent's RT page]</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=CannedReplies&diff=26517CannedReplies2017-09-07T02:06:44Z<p>Barton: Code reformatting</p>
<hr />
<div>Several people have asked on the mailing list about how to get 'canned replies' to appear in a drop-down list on the reply/comment screen. The idea is to make frequently used responses easily accessible.<br />
<br />
RTFM gives this capability.<br />
<br />
There may be people who don't need the full power (and overhead) of an RTFM installation. For these folks, here is a simple solution that uses a couple of callbacks to provide a canned-reply feature on the reply/comment screen. It uses RT's templates, so the same variable substitutions can be used. One limitation is that the transaction object can't be used in the template - I just pass in a blank transaction object to the template parsing routine.<br />
<br />
Users will need [[ShowTemplate]] rights in order to send canned replies.<br />
<br />
Also note that you can send a canned reply with a quoted messages, but that the textarea will combine them in the style of a top post.<br />
<br />
----<br />
<br />
== Modified Version ==<br />
<br />
by Kevin "gentgeen" Squire (gentgeen AT wikiak DOT org) on Mar 5, 2010.<br />
<br />
One drawback of the original [[CannedReplies]] was that it showed all templates in the dropdown. Originally this was fine for our environment, but as we began using RT for more things, and the pool of privileged users became less technical, there was a call to filter out the templates that were not canned replies. This is what I did meet that goal. All of my work is based off of the original done by Stephen Turner(MIT).<br />
<br />
=== Create a SelectCannedReply Admin Element ===<br />
<br />
Bring a copy of the SelectTemplate element over to you local branch and call it SelectCannedReply:<br />
<br />
cp $RTHOME/html/Admin/Elements/SelectTemplate $RTHOME/local/html/Admin/Elements/SelectCannedReply<br />
<br />
Modify the SelectCannedReply file. I added a line right before the "OrderBy" line in each of the functions. Mine now looks like this:<br />
<br />
<%INIT><br />
my $PrimaryTemplates = RT::Templates->new($session{'CurrentUser'});<br />
if ($Queue != 0) {<br />
$PrimaryTemplates->LimitToQueue($Queue);<br />
$PrimaryTemplates->Limit(FIELD => 'Description', OPERATOR => 'STARTSWITH', VALUE => 'Canned Reply');<br />
$PrimaryTemplates->OrderBy(FIELD => 'Name');<br />
}<br />
<br />
my $OtherTemplates = RT::Templates->new($session{'CurrentUser'});<br />
$OtherTemplates->LimitToGlobal($DefaultQueue);<br />
$OtherTemplates->Limit(FIELD => 'Description', OPERATOR => 'STARTSWITH', VALUE => 'Canned Reply');<br />
$OtherTemplates->OrderBy(FIELD => 'Name');<br />
</%INIT><br />
<br />
=== Create The Two Callbacks ===<br />
<br />
These are basically identical to the original version, the one major difference was the call is now made to /Admin/Elements/SelectCannedReply instead of /Admin/Elements/SelectTemplate<br />
<br />
==== $RTHOME/local/html/Callbacks/CannedReply/Ticket/Update.html/BeforeMessageBox ====<br />
<br />
<tr><br />
<td>Canned-reply:</td><br />
<td><& /Admin/Elements/SelectCannedReply, Name => "Canned-Template", Queue => $TicketObj->QueueObj->id &><br />
<input type="submit" name="select_template" value="Go"><br />
</tr><br />
<br />
<%init><br />
my $TicketObj = LoadTicket($ARGS{'id'});<br />
</%init><br />
</td><br />
<br />
==== $RTHOME/local/html/Callbacks/CannedReply/Elements/MessageBox/Default ====<br />
<br />
identical to the original $RTHOME/local/html/Callbacks/&lt;whatever&gt;/Elements/MessageBox/Default below.<br />
<br />
=== Usage ===<br />
<br />
Like the original, you use RT's templates to create your canned-replies. so the same variable substitutions can be used. You can create your canned-replies as a global template (A canned-reply for use in every queue) or just within the queue (A canned-reply for use in just the one queue). The difference in this setup from the original is that it will limit what is shown to the end-user based on the ''description'' of the template. When creating a canned-reply, you will need to make your description begin with "Canned Reply" (case sensitive). This can be altered (Non-English languages for example) by modifying the "STARTSWITH" option in the SelectCannedReply file.<br />
<br />
Users will need [[ShowTemplate]] rights in order to send canned replies.<br />
<br />
----<br />
<br />
== Original ==<br />
<br />
by Stephen Turner (MIT) on April 6, 2006.<br />
<br />
Here's the code - this involves two new Callback files. Please note that this is just something I've been playing with, and there is probably room for improvement.<br />
<br />
=== $RTHOME/local/html/Callbacks/&lt;whatever&gt;/Ticket/Update.html/BeforeMessageBox ===<br />
<br />
Canned reply: <& /Admin/Elements/SelectTemplate, Name => "Canned-Template", Queue => $TicketObj->QueueObj->id &><br />
<input type="submit" name="select_template" value="Go"><br />
<br />
<%init><br />
my $TicketObj = LoadTicket($ARGS{'id'});<br />
</%init><br />
<br />
=== $RTHOME/local/html/Callbacks/<whatever>/Elements/MessageBox/Default ===<br />
<br />
%#<br />
%# Allows use of templates as 'canned replies' in update screen.<br />
%# Looks up the template specified, parses it and displays the parsed<br />
%# template content.<br />
%#<br />
% if ($content) {<br />
<% $content %><br />
% }<br />
<%init><br />
my $template;<br />
my $trans = new RT::Transaction( $session{'CurrentUser'} );<br />
my $content = "";<br />
<br />
if ( $ARGS{'select_template'} ) {<br />
my $template_id = $ARGS{'Canned-Template'};<br />
if ($template_id) {<br />
$template = RT::Template->new($session{'CurrentUser'});<br />
$template->Load($template_id);<br />
if ($template->id) {<br />
my $TicketObj = LoadTicket($ARGS{'id'});<br />
$template->Parse(TicketObj => $TicketObj,<br />
TransactionObj => $trans);<br />
$content = $template->MIMEObj->stringify;<br />
}<br />
}<br />
<br />
}<br />
</%init><br />
<br />
<br />
== Pretty Variation 1 ==<br />
<br />
by Kevin "gentgeen" Squire (gentgeen AT wikiak DOT org)<br />
<br />
I really liked the original idea, but I did not like how it was displayed. I wanted the words "Canned reply:" to be directly above the word "Message" and the templates selection and submit button to line up with the other input boxes.<br />
<br />
The code above will create a table that looks something like this:<br />
<br />
--------------------------------------------------------------<br />
| Bcc: | INPUTBOX |<br />
| Attach: | INPUTBOX BUTTON BUTTON |<br />
| Message: | Canned Reply: DROPDOWNBOX BUTTON |<br />
| INPUTBOX |<br />
--------------------------------------------------------------<br />
<br />
<br />
The code below will create a table that looks something like this:<br />
<br />
------------------------------------------------<br />
| Bcc: | INPUTBOX |<br />
| Attach: | INPUTBOX BUTTON BUTTON |<br />
| Canned Reply: | DROPDOWNBOX BUTTON |<br />
| Message: | INPUTBOX |<br />
------------------------------------------------<br />
<br />
First I changed the Update.html page (I copied the original over to my local directory) by adding a call to a callback for "[[BeforeMessage]]" (instead of "[[BeforeMessageBox]]"<br />
<br />
=== New Update.html ===<br />
<br />
<tr><td align=right><&|/l&>Attach</&>:</td><td><input name="Attach" type="file"><INPUT TYPE=SUBMIT NAME="AddMoreAttach" VALUE="<&|/l&>Add More Files</&>"><input type="hidden" name="UpdateAttach" value="1"><br />
</td></tr><br />
<br />
<!-- Adding New Call Back Here --><br />
<& /Elements/Callback, _CallbackName => 'BeforeMessage', %ARGS &><br />
<!-- End of New Call Back --><br />
<br />
<tr><td align="right" valign="top"><&|/l&>Message</&>:</td><td><br />
<& /Elements/Callback, _CallbackName => 'BeforeMessageBox', %ARGS &><br />
<br />
<br />
'''<nowiki>*NOTE:</nowiki>'''* Since the callback is in the middle of a table, the callback code must be at least 1 table row, with two table data elements<br />
<br />
Then I changed the first callback noted above to the following:<br />
<br />
=== $RTHOME/local/html/Callbacks/<whatever>/Ticket/Update.html/BeforeMessage ===<br />
<br />
%#<br />
%# Allows use of templates as 'canned replies' in update screen.<br />
%# Presents a select list of templates.<br />
%#<br />
<tr><br />
<td class="label">Canned reply:</td><br />
<td colspan="2"><& /Admin/Elements/SelectTemplate, Name => "Canned-Template", Queue => $TicketObj->QueueObj->id &><br />
<input type="submit" name="select_template" value="Go"><br />
</td><br />
</tr><br />
<br />
<%init><br />
my $TicketObj = LoadTicket($ARGS{'id'});<br />
</%init><br />
<br />
== Simpler Pretty Variation ==<br />
<br />
by Jerrad<br />
<br />
This uses the original's MessageBox callback, but instead of local/html/Callbacks/Indirection/Ticket/Update.html/BeforeMessageBox we use local/html/Callbacks/Indirection/Ticket/Update.html/BeforeUpdateType with:<br />
<br />
<td><br />
<& /Admin/Elements/SelectTemplate, Name => "Canned-Template", Queue => $TicketObj->QueueObj->id &><br />
<input type="submit" name="select_template" value="Load"><br />
</td></tr><br />
<br />
<%init><br />
my $TicketObj = LoadTicket($ARGS{'id'});<br />
</%init><br />
<br />
<br />
== DefaultCreateContent; yet another version ==<br />
<br />
[http://lists.bestpractical.com/pipermail/rt-users/2011-February/068854.html mailing list post]<br />
<br />
== See Also ==<br />
<br />
[[StockAnswers]]</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=ObjectModel&diff=26516ObjectModel2017-09-03T21:26:44Z<p>Barton: /* Singular vs plural file names */</p>
<hr />
<div>= Introduction =<br />
<br />
'''NOTE:''' This document expects that you're using default installation directory of /opt/rt3. Relative paths are all against /opt/rt3.<br />
<br />
= Files in library =<br />
<br />
== Base files ==<br />
<br />
&gt; ls lib/RT/ | grep '^Queue'<br />
Queue_Overlay.pm<br />
Queue.pm<br />
Queues_Overlay.pm<br />
Queues.pm<br />
<br />
<code>Queue.pm</code> is the base file for the RT::Queue package. You can list all RT packages and their base files with command:<br />
<br />
&gt; find lib/RT -name '*.pm' | \<br />
perl -ne 'print $_ unless /Overlay|Local|Vendor/' | \<br />
xargs grep '^package '<br />
<br />
lib/RT/ACE.pm:package RT::ACE;<br />
lib/RT/ACL.pm:package RT::ACL;<br />
lib/RT/Action/AutoOpen.pm:package RT::Action::AutoOpen;<br />
lib/RT/Action/Autoreply.pm:package RT::Action::Autoreply;<br />
lib/RT/Action/CreateTickets.pm:package RT::Action::CreateTickets;<br />
...<br />
<br />
As you can see almost all files that have no '_' character in the file name define a package.<br />
<br />
== Overlay, Local and Vendor files ==<br />
<br />
&gt; cat Queue.pm<br />
...<br />
eval "require RT::Queue_Overlay";<br />
if ($@ &amp;&amp; $@ !~ qr{^Can't locate RT/Queue_Overlay.pm}) {<br />
die $@;<br />
};<br />
<br />
This code tries load the file lib/RT/[[Queue Overlay|Queue_Overlay]].pm. If the file doesn't exist then RT will silently ignore it. On other errors RT will throw an exception. lib/RT/[[Queue Overlay|Queue_Overlay]].pm has no package definition so all code in it loads into RT::Queue package(name-space)<br />
<br />
If Queue_Overlay.pm defines a subroutine already present in Queue.pm Perl will override the original subroutine from Queue.pm with subroutine in Queue_Overlay.pm. Almost all base files (packages) load overrides from _Overlay.pm, _Vendor.pm and _Local.pm files. RT loads files in predefined order: the _Local.pm file is last and its subroutines have highest priority.<br />
<br />
RT uses this technique because RT many base files (Queue.pm, Ticket.pm, etc) are generated automatically from information about data base. From the file's heading:<br />
<br />
<nowiki># Autogenerated by DBIx::SearchBuilder factory (by &lt;jesse@bestpractical.com&gt;)<br />
# WARNING: THIS FILE IS AUTOGENERATED. ALL CHANGES TO THIS FILE WILL BE LOST.<br />
#<br />
# !! DO NOT EDIT THIS FILE !!<br />
<br />
</nowiki><br />
<br />
See also: [[CleanlyCustomizeRT]]<br />
<br />
== So many overlaying files where to look? ==<br />
<br />
Again, on example. There is a Queues table in the DB, so Queue.pm is autogenerated from table schema and RT developers use [[Queue Overlay|Queue_Overlay]].pm. [[Queue Vendor|Queue_Vendor]].pm is for distributors packaging RT with extensions and fixes. [[Queue Local|Queue_Local]].pm is for end-administrators for customization. If you want to know more about Queue class and its methods then you look at Queue.pm for basic list of methods to access data fields and then at [[Queue Overlay|Queue_Overlay]].pm to get more advanced methods.<br />
<br />
== Singular vs plural file names ==<br />
<br />
Table in DB is a <u>collection</u> of the <u>records</u>. RT has tickets(collection). When you search tickets you limit collection with some conditions, each item in the collection is a ticket(record). So each table is represented with two classes. One represent a record in the table, second represent the table like collection of records.<br />
<br />
{| border="1"<br />
|- valign="top"<br />
| Records<br />
| Collections(tables)<br />
|- valign="top"<br />
| ACE.pm<br />
| ACL.pm<br />
|- valign="top"<br />
| Attachment.pm<br />
| Attachments.pm<br />
|- valign="top"<br />
| [[CachedGroupMember]].pm<br />
| [[CachedGroupMembers]].pm<br />
|- valign="top"<br />
| [[CustomField]].pm <br />
| [[CustomFields]].pm <br />
|- valign="top" <br />
| [[CustomFieldValue]].pm<br />
| [[CustomFieldValues]].pm <br />
|- valign="top"<br />
| [[GroupMember]].pm <br />
| [[GroupMembers]].pm<br />
|- valign="top"<br />
| Group.pm<br />
| Groups.pm<br />
|- valign="top"<br />
| Link.pm<br />
| Links.pm<br />
|- valign="top"<br />
| Principal.pm<br />
| Principals.pm<br />
|- valign="top"<br />
| Queue.pm<br />
| Queues.pm<br />
|- valign="top"<br />
| [[ScripAction]].pm <br />
| [[ScripActions]].pm <br />
|- valign="top"<br />
| [[ScripCondition]].pm <br />
| [[ScripConditions]].pm <br />
|- valign="top"<br />
| Scrip.pm<br />
| Scrips.pm<br />
|- valign="top"<br />
| Template.pm<br />
| Templates.pm<br />
|- valign="top"<br />
| [[TicketCustomFieldValue]].pm <br />
| [[TicketCustomFieldValues]].pm<br />
|- valign="top"<br />
| Ticket.pm<br />
| Tickets.pm<br />
|- valign="top"<br />
| Transaction.pm<br />
| Transactions.pm<br />
|- valign="top"<br />
| User.pm<br />
| Users.pm<br />
|}<br />
<br />
Classes listed in the left column are inherited from <code>RT::Record</code> class. The right column represents classes inherited from [=RT::[[SearchBuilder]]] class. Both(Record and SearchBuilder) are major classes that provide a platform (based on [=[[DBIx]]::[[SearchBuilder]]] framework) to manipulate RT's DB.<br />
<br />
See below about records and collections.<br />
<br />
== How local folder works ==<br />
<br />
In RT files hierarchy there is <code>local</code> folder that has special meaning, see [[CleanlyCustomizeRT]] for details.<br />
<br />
= API =<br />
<br />
== RT::Base ==<br />
<br />
Base class for all RT classes. Implements minor functionality that is general for all classes. Provides several methods, description below.<br />
<br />
perldoc lib/RT/Base.pm<br />
<br />
=== CurrentUser ===<br />
<br />
When you construct RT objects from classes then you should define user context. Example: [=my $ticket = RT::Ticket-&gt;new( $RT::[[SystemUser]] );] with this code you create an object of RT::Ticket class in context of SystemUser(see below about SystemUser). You can do everything with the ticket now, but if you create a ticket object in context of user 'John' then some operations may fail because of right restrictions.<br />
<br />
This sub also allows you to change user context. For example, if you get a ticket object from external code and want to execute code that shouldn't fail even if the user doesn't have some rights, then you can switch to SystemUser do what you need and then switch back. Code example:<br />
<br />
my $old_user = $ticket-&gt;CurrentUser;<br />
$ticket-&gt;CurrentUser( $RT::SystemUser );<br />
...<br />
$ticket-&gt;CurrentUser( $old_user );<br />
<br />
* [=$RT::[[SystemUser]]] is described in [[GlobalObjects]] page<br />
<br />
If some object method returns other RT object then the returned object is also in the same user context as original object. Example:<br />
<br />
my $queue = $ticket-&gt;QueueObj;<br />
my $cur_user = $queue-&gt;CurrentUser; # same user as for $ticket<br />
<br />
=== loc ===<br />
<br />
i18n stuff, see examples in code, how RT uses it and also see [=perldoc Locale::Maketext].<br />
<br />
== RT::Record ==<br />
<br />
Base class for records in tables. This class allows you to:<br />
<br />
* load a record that already exists by one column value or by several column values;<br />
<br />
<nowiki>use RT::Ticket;<br />
my $TicketObj = new RT::Ticket( $RT::SystemUser );<br />
# loads ticket with id = 1<br />
$TicketObj-&gt;Load( 1 );<br />
</nowiki><br />
<br />
* create new record;<br />
<br />
<nowiki>use RT::Ticket;<br />
my $TicketObj = new RT::Ticket( $RT::SystemUser );<br />
# creates new ticket<br />
$TicketObj-&gt;Create( Queue =&gt; 1, Subject =&gt; ' ' );<br />
</nowiki><br />
<br />
* after you load or create new record, you can get or set its column values;<br />
<br />
<nowiki>$TicketObj-&gt;Load( 1 );<br />
# gets current subject<br />
my $subject = $TicketObj-&gt;Subject;<br />
# adds urgent mark to old subject and updates ticket<br />
$TicketObj-&gt;SetSubject("urgent: $subject");<br />
</nowiki><br />
<br />
* get other objects that relates to the current.<br />
<br />
my $transactions = $TicketObj-&gt;Transactions;<br />
<br />
=== [=Set*], [=_Set] and [=__Set] methods ===<br />
<br />
* You call [=[[SetXxxx]]( $Value )] method of the RT object.<br />
** If perl can't find method, <code>AUTOLOAD</code> is called.<br />
*** <code>AUTOLOAD</code> splits [=[[SetXxxx]]] into 'Set' and 'Xxxx'<br />
*** Check is there accesible field in object? No?! Then RT will die.<br />
*** Is field mutable or readonly. Return error if readonly.<br />
*** Create alias: [=[[SetXxxx]]($Value) ~ _Set(Field =&gt; 'Xxxx', Value =&gt; $Value)]<br />
*** Call alias.<br />
** Next time RT will find this function because of alias.<br />
* <code>_Set</code> actually comes from [=[[SearchBuilder]]], this function is specially intended for inheritance.<br />
** RT check user rights here and do some magic if needed.<br />
** If everything is allright <code>_Set</code> calls <code>__Set</code> which updates DB. <code>__Set</code> rare does more magic.<br />
<br />
== RT::SearchBuilder ==<br />
<br />
Base class for collections of records(tables). This class has several groups of functions that alow you to:<br />
<br />
* limit collection from all records in table to several records that match some conditions;<br />
* walk through this collection and get first, last, next, prev records or by index;<br />
* change records order by colum values;<br />
* limit collection with conditions based on other tables via relationships of tables.<br />
<br />
== RT API docs ==<br />
<br />
Perl supports POD(Plain Old Documentation) embeded into code. RT uses POD to describe methods of the clases. You can view this documentation with <code>perldoc</code> utility that comes with perl.<br />
<br />
perldoc /www/rt3/lib/RT/CustomField_Overlay.pm<br />
<br />
Also you can use [http://search.cpan.org/dist/RT-OnlineDocs RT::OnlineDocs] module.<br />
<br />
== RT API Inspector ==<br />
<br />
I wrote a small snippet that uses [http://search.cpan.org/~adamk/Class-Inspector-1.13/ Class::Inspector] to show which methods are available to specific RT objects.<br />
<br />
http://www.cpan.org/authors/id/A/AH/AHARRISON/scripts/rt-class-map-1.3.pl</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=NewTicketsAlert&diff=26515NewTicketsAlert2017-08-25T16:24:59Z<p>Barton: Code formatting cleanup</p>
<hr />
<div>This callback adds a conspicuous message on the top of the "My RT" page which displays a list of new tickets assigned to the current user. It also adds a count of the user's new tickets in the page title, ie. "My RT (2)". <br />
<br />
Place this in '''Callbacks/NewTicketsAlert/Elements/MyRT/BeforeTable''' :<br />
<br />
% if ($count > 0) {<br />
<div class="results"><br />
<script type="text/javascript">document.title += " (<%$count%>)"</script><br />
<&|/Widgets/TitleBox, title => $title &><br />
<ul><br />
% while (my $ticket = $tickets->Next) {<br />
<li><a href="/Ticket/Display.html?id=<%$ticket->Id%>">#<%$ticket->Id%>:&nbsp;<%$ticket->Subject%></a></li><br />
% }<br />
</ul><br />
</&><br />
</div><br />
% }<br />
<%INIT><br />
my $tickets = RT::Tickets->new( $session{'CurrentUser'} );<br />
$tickets->LimitOwner( VALUE => $session{'CurrentUser'}->Id );<br />
$tickets->LimitStatus( VALUE => 'new' );<br />
my $count = $tickets->CountAll();<br />
my $title;<br />
if ($count == 1) {<br />
$title = "You have a new ticket";<br />
} else {<br />
$title = "You have ${count} new tickets";<br />
}<br />
</%INIT></div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=AddRequestor&diff=26514AddRequestor2017-08-23T12:46:21Z<p>Barton: /* Solution */</p>
<hr />
<div>== Problem ==<br />
<br />
We have clients with more than one contact in them enterprises.<br />
<br />
All clients of a same enterprise want to see the tickets.<br />
<br />
== Solution ==<br />
<br />
* Create a custom field (user account) with the list of mail to add to the ticket as Requestor. (Do it for all client).<br />
<br />
Login as root :<br />
Configuration -> Custom Field -> new Custom Field<br />
<br />
Name : othermail<br />
Description : the list of another e-mail user of the same enterprise<br />
Type : Enter Multiple Value<br />
Applies to : Users<br />
Validation :<br />
Enable : x<br />
Link value to :<br />
include page :<br />
<br />
* On Ticket Creation : auto add the list of e-mails as Requestor<br />
<br />
Login as root :<br />
Configuration -> Global -> Scrips -> new Scrip<br />
Description : AddOwnerForEntreprises<br />
Condition : On Create<br />
Action : User Defined<br />
Template : Global Template : Blank<br />
Stage : TransactionCreate<br />
<br />
Custom conditions :<br />
<br />
Return 1;<br />
<br />
Custom action preparation code:<br />
<br />
# Get Current Ticket<br />
my $T_Obj = $self->TicketObj;<br />
my $Email_Rq = $T_Obj->RequestorAddresses;<br />
<br />
# Set objet for User and Other<br />
my $U_Obj = RT::User->new($RT::SystemUser);<br />
my $O_Obj = RT::User->new($RT::SystemUser);<br />
<br />
$U_Obj->LoadByEmail($Email_Rq);<br />
<br />
my $cf_name="othermail";<br />
my $others=$U_Obj->FirstCustomFieldValue($cf_name);<br />
<br />
#if the field contiens lot of mails (separated by ",")<br />
$others =~ s/\n//g; #(remove \n)<br />
my @other_list=split(/,/,$others);<br />
<br />
#param request-field to add Other<br />
my $Rq_Obj = $T_Obj->Requestors;<br />
my $other_id;<br />
my $other_mail;<br />
foreach $other_mail (@other_list)<br />
{<br />
# get the user via email address<br />
$O_Obj->LoadByEmail($other_mail);<br />
<br />
# get Id<br />
$other_id = $O_Obj->Id;<br />
<br />
# Add user<br />
$Rq_Obj->AddMember($other_id);<br />
}<br />
<br />
return 1;<br />
<br />
<br />
Custom action cleanup code:<br />
return 1;<br />
<br />
== Example ==<br />
<br />
user1 ([mailto:user1@test.com user1@test.com]), user2 ([mailto:user2@test.com user2@test.com]) and user3 ([mailto:user3@test.com user3@test.com]) are in the same entreprise<br />
<br />
on the CF "othermail" of user1 [mailto:user2@test.com user2@test.com], [mailto:user3@test.com user3@test.com]<br />
<br />
and<br />
<br />
on the CF "othermail" of user2 : [mailto:user1@test.com user1@test.com], [mailto:user3@test.com user3@test.com]<br />
<br />
and<br />
<br />
on the CF "othermail" of user3 : [mailto:user1@test.com user1@test.com], [mailto:user2@test.com user2@test.com]<br />
<br />
when user1 create a ticket, user2 and user3 can view the ticket</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=Talk:ShowPerQueueInstructions&diff=26513Talk:ShowPerQueueInstructions2017-08-20T17:07:59Z<p>Barton: Created page with "Need an rt4 version of this page."</p>
<hr />
<div>Need an rt4 version of this page.</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=ShowPerQueueInstructions&diff=26512ShowPerQueueInstructions2017-08-20T17:06:13Z<p>Barton: Code formatting cleanup</p>
<hr />
<div>= Specify Per-Queue instructions before message box =<br />
<br />
For certain queues, I like to have additional messages for users, telling them exactly what information is needed.<br />
<br />
You can create <tt>/opt/rt3/local/html/Callbacks/MyCallbacks/Ticket/Create.html/BeforeMessageBox</tt> with the following contents:<br />
<br />
% if ( $QueueObj->Name eq 'MyQueue' ) {<br />
<b> MyQueue Specific Info Here </b><br />
% }<br />
<br />
<%ARGS><br />
$QueueObj => undef<br />
</%ARGS><br />
<br />
--Jim Perrin<br />
<br />
= See Also =<br />
<br />
[[CustomizingWithCallbacks]]</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=AddCustomStyleSheet&diff=26511AddCustomStyleSheet2017-08-20T16:57:51Z<p>Barton: Formatting fix for header code.</p>
<hr />
<div>= Using a Callback to Add a StyleSheet (Chuck Boeheim, Gary Oberbrunner) =<br />
<br />
As of 3.8.2 at least, you can add things to main.css by putting them in<br />
<br />
/opt/rt3/local/html/Callbacks/ANYTHING/NoAuth/css/web2/main.css/End<br />
<br />
and anything you put there will get stuffed into main-squished.css.<br />
<br />
Here's the older text that was on this page, for reference:<br />
<br />
===<br />
<br />
There isn't currently a place provided to load an additional stylesheet in the header processing, but there is a general Header callback.<br />
<br />
Putting the following file in /opt/rt3/local/html/Callbacks/SLAC/Elements/Header/Head<br />
<br />
%# SLAC Addition to load another stylesheet on request.<br />
&lt;%args&gt;<br />
$Stylesheet =&gt; undef<br />
&lt;/%args&gt;<br />
&lt;!-- Local header included --&gt;<br />
% if ($Stylesheet) {<br />
&lt;link rel="stylesheet" href="&lt;% $Stylesheet %&gt;" type="text/css" /&gt;<br />
% }<br />
<br />
<br />
allows one to add 'Stylesheet = "/path/to/stylesheet"' to the call to the header component on any given page. I've been using this to add some styles needed for some custom input forms I've been doing. A sample call at the top of one of my forms is:<br />
<br />
<& Elements/Header, Title => "Phone Install/Feature Change Request",<br />
Stylesheet => "$RT::WebPath/Forms/css/forms.css" &><br />
<br />
<br />
= See also =<br />
<br />
[[CustomizingWithCallbacks]]</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=EmailRouting&diff=26510EmailRouting2017-08-18T02:19:09Z<p>Barton: </p>
<hr />
<div>== HowTo Request-Tracker Email Routing using Scrips ==<br />
<br />
http://howtoforums.net/viewtopic.php?p=32#32<br />
<br />
If you're going to route different emails to different queues based on domains then you might just find this "Scrip" useful. Scrip - is a terminology used in Request-Tracker to basically create an automatic rule based on a condition.<br />
<br />
1. Make sure the system group "Everyone" has the following permissions on the General Queue:<br />
<br />
<nowiki>* CreateTicket<br />
* Comment on Ticket<br />
* Reply on Ticket<br />
</nowiki><br />
<br />
2. Create a Scrip on the "General" queue using the parameters below.<br />
<br />
Description: Scrip Description<br />
Condition: On Create<br />
Action: User Defined<br />
Template: Global Template Blank<br />
Stage: TransactionCreate<br />
<br />
Custom action preparation code:<br />
<br />
<tt> return 1;</tt><br />
<br />
Custom action cleanup code:<br />
<br />
# Domains we want to move<br />
my $domains = {};<br />
<br />
my %domain_map = (<br />
'\@gmail\.com' => "Queue 1",<br />
'\@yahoo\.com' => "Queue 2",<br />
'\@hotmail\.com' => "Queue 3",<br />
);<br />
<br />
#Check each of our defined domains for a match<br />
foreach my $domainKey (keys %domain_map ){<br />
if($self->TicketObj->RequestorAddresses =~ /^.*?${domainKey}/) {<br />
# Domain matches - move to the right queue<br />
$self->TicketObj->SetQueue($domain_map{$domainKey});<br />
}<br />
}<br />
<br />
And of course modify this part to suite your own needs:<br />
<br />
<tt> '\@gmail\.com' =&gt; "Queue 1",</tt><br />
<br />
Enjoy !<br />
<br />
Jacob Baloul http://howtoforums.net</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=EmailRouting&diff=26509EmailRouting2017-08-18T02:17:01Z<p>Barton: Formatting cleanup</p>
<hr />
<div>== HowTo Request-Tracker Email Routing using Scrips ==<br />
<br />
http://howtoforums.net/viewtopic.php?p=32#32<br />
<br />
If you're going to route different emails to different queues based on domains then you might just find this "Scrip" useful. Scrip - is a terminology used in Request-Tracker to basically create an automatic rule based on a condition.<br />
<br />
1. Make sure the system group "Everyone" has the following permissions on the General Queue:<br />
<br />
<nowiki>* CreateTicket<br />
* Comment on Ticket<br />
* Reply on Ticket<br />
</nowiki><br />
<br />
2. Create a Scrip on the "General" queue using the parameters below.<br />
<br />
Description: Scrip Description<br />
Condition: On Create<br />
Action: User Defined<br />
Template: Global Template Blank<br />
Stage: TransactionCreate<br />
<br />
Custom action preparation code:<br />
<br />
return 1;<br />
<br />
Custom action cleanup code:<br />
<br />
# Domains we want to move<br />
my $domains = {};<br />
<br />
my %domain_map = (<br />
'\@gmail\.com' => "Queue 1",<br />
'\@yahoo\.com' => "Queue 2",<br />
'\@hotmail\.com' => "Queue 3",<br />
);<br />
<br />
#Check each of our defined domains for a match<br />
foreach my $domainKey (keys %domain_map ){<br />
if($self->TicketObj->RequestorAddresses =~ /^.*?${domainKey}/) {<br />
# Domain matches - move to the right queue<br />
$self->TicketObj->SetQueue($domain_map{$domainKey});<br />
}<br />
}<br />
<br />
And of course modify this part to suite your own needs:<br />
<br />
'\@gmail\.com' =&gt; "Queue 1",<br />
<br />
Enjoy !<br />
<br />
Jacob Baloul http://howtoforums.net</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=TicketSQL&diff=26508TicketSQL2017-08-18T01:44:09Z<p>Barton: Formatting cleanup</p>
<hr />
<div>[[TicketSQL]] is RT's loose variant of SQL that you can use for composing custom queries by hand:<br />
<br />
* in RT's web interface on the Query Builder page (click Advanced)<br />
* on the command-line: [[UseRtCrontool|$RTHOME/bin/rt-crontool]] or [[UseRtTool|$RTHOME/bin/rt]], the general-purpose command-line tool<br />
* in RT's Perl API<br />
<br />
For the time being, the best way to learn [[TicketSQL]] is to compose queries using Query Builder and then click Advanced to see the generated [[TicketSQL]] code.<br />
<br />
== Special placeholders ==<br />
<br />
If you would like to search relative to the current user, you can click Advanced and enter something like<br />
<br />
<tt> (Owner = '__CurrentUser__')</tt><br />
<br />
You can use __CurrentUser__ anywhere you'd use a user id. This is really useful for building saved searches for people.<br />
<br />
e.g. <tt>Owner = '__CurrentUser__' AND Status != 'resolved'</tt><br />
<br />
Bookmarked tickets can be searched too:<br />
<br />
<tt> id = '__Bookmarked__'</tt><br />
<br />
== Date Syntax ==<br />
<br />
Date statements take the following form <code><Field> <Operator> <Date></code>. Field is some Ticket Field of type date. Operator is the comparison Operator. Date is a date value.<br />
<br />
Valid operators include:<br />
<br />
* <tt>&lt;</tt> (less than)<br />
* <tt>&lt;=</tt> (less than or equal to)<br />
*<br />
<tt><br />
=</tt> (equals)<br />
* <tt>!=</tt> (not equal to)<br />
* <tt>&gt;</tt> (greater than)<br />
* <tt>&gt;=</tt> (greater than or equal to)<br />
<br />
There are at least three valid date formats:<br />
<br />
* <tt>today</tt> uses today's date as the date value<br />
* <tt>x days ago</tt> where x is some integer value (e.g. 8 days ago)<br />
* <tt>YYYY-MM-DD</tt> absolute day in the format year-month-date (e.g. {{CURRENTYEAR}}-{{CURRENTMONTH}}-{{CURRENTDAY2}})<br />
* <tt>'n seconds'</tt>, <tt>'n minutes'</tt>, <tt>'n hours'</tt>, <tt>'n days'</tt>, <tt>'n weeks'</tt> are dates in the future relative to the current date, ie current_date + n minutes. May be negative, eg '-2 days' is two days in the past.<br />
Consult the [https://metacpan.org/pod/Time::ParseDate#DATE-FORMATS-RECOGNIZED Time::ParseDate documentation] for all valid date/time formats.<br />
<br />
== Examples ==<br />
<br />
Tickets in the General queue that are new or open and owned by joe:<br />
<br />
<tt>(Status = 'new' OR Status = 'open') AND Queue = 'General' AND owner = 'joe'</tt><br />
<br />
Searching by date:<br />
<br />
<tt>Created &gt; '7 days ago' AND Queue = 'General'</tt><br />
<br />
<tt>Status = 'stalled' AND Due &lt;= 'today'</tt><br />
<br />
Accessing custom fields:<br />
<br />
<tt> Status = 'resolved' AND CF.YourCustomField = 'somevalue'</tt><br />
<br />
Tickets that have no members (children):<br />
<br />
<tt> HasMember = 'NULL'</tt><br />
<br />
Tickets that depend on at least one other ticket:<br />
<br />
<tt> DependsOn != 'NULL'</tt><br />
<br />
== Perl API ==<br />
<br />
my $tickets = RT::Tickets->new(RT->SystemUser);<br />
'''$tickets->FromSQL($tsql);'''<br />
while (my $t = $tickets->Next) {<br />
# do stuff with each ticket $t here<br />
print $t->Subject, "\n";<br />
}</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=WritingPortlets&diff=26474WritingPortlets2017-01-08T23:20:59Z<p>Barton: /* Installing a portlet into RT-at-a-glance */</p>
<hr />
<div>= How to write a Homepage Component (Portlet) =<br />
<br />
Portlets are the panels that appear in your "RT-at-a-glance" home page, such as "n Highest Priority Tickets I own", "Quick Ticket Creation" and "Quick Search". When you click on the "Edit" link on your home page (or go there via your preferences), you can select which of the available portlets are displayed in the "body" (left) or "summary" (right) columns of the home page.<br />
<br />
They can also appear on the Self-Service interface, but have to be hard-coded, because Self-Service users don't get the same preferences available to them. You need to manually edit &lt;rt-base-dir&gt;/local/html/SelfService/index.html. You just have to create your element in &lt;rt-base-dir&gt;/local/html/SelfService/Elements and call it from within the index.html file with something like:<br />
<br />
&lt;&amp; /SelfService/Elements/[[MyPortlet]] &amp;&gt;<br />
<br />
This example works with RT 3.8.8 and may work with older versions too - your mileage may vary.<br />
<br />
There are at least two things you have to do to create a portlet:<br />
<br />
# Create a MASON template file in &lt;rt-base-dir&gt;/local/html/Elements that defines your portlet's behaviour.<br />
# Install your portlet by adding it's name to the HomepageComponents configuration variable in RT_SiteConfig.pm.<br />
<br />
Once you have created and installed your portlet, you of course, have to restart Apache.<br />
<br />
== Create a MASON template file ==<br />
<br />
Here's an example MASON template which creates an inline frame containing a web-page from another site:<br />
<br />
&lt;&amp;|/Widgets/TitleBox, title =&gt; loc('External Page')&amp;&gt;<br />
&lt;table&gt;<br />
&lt;tr&gt;<br />
&lt;td&gt; &lt;iframe name="external page" src="http://wiki.bestpractical.com/" height="480" width="640" frameborder="0" &gt;<br />
&lt;/iframe&gt;<br />
&lt;/td&gt;<br />
&lt;/tr&gt;<br />
&lt;/table&gt;<br />
&lt;/&amp;&gt;<br />
<br />
For this example, the file is saved as "ExternalPage" in the &lt;rt-base-dir&gt;/local/html/Elements directory.<br />
<br />
== Installing a portlet into RT-at-a-glance ==<br />
<br />
Edit your RT_SiteConfig.pm file, and edit the $HomepageComponents variable (if it hasn't got one, copy it from the RT_Config.pm file). Add the name of your MASON template file, in this example, "ExternalPage":<br />
<br />
Set($HomepageComponents, [qw(QuickCreate Quicksearch MyCalendar<br />
MyAdminQueues MySupportQueues MyReminders RefreshHomepage<br />
ExternalPage<br />
)]);<br />
<br />
Go to the "RT at a glance" page, click on the "Edit" link in the top right corner.<br />
<br />
In the "Customize RT at a glance" page, add the ExternalPage portlet to the section you prefer, by choosing it in one of the left-hand columns and then clicking on the button that resembles a right arrow.</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=SendNagiosAlert&diff=26473SendNagiosAlert2017-01-08T22:40:11Z<p>Barton: </p>
<hr />
<div>Here's a [[Scrip]] that you can use to send an alert to [http://www.nagios.org Nagios] if a ticket is new or open in a particular [[Queue]](s). This scrip will only run if a ticket is created, a ticket's status is changed, or a ticket is moved to another queue. If one of these conditions is met, then it will looked at each queue defined in the scrip to see if there are any open or new [[Ticket]]s in those queues. If there are no tickets in that queue, it will send an OK to the corresponding nagios service. If there are new or open tickets in that queue, it will send a CRITICAL to the corresponding nagios alert.<br />
<br />
You must have Nagios already configured for this passive check, have send_nsca installed on the RT server, and the nsca [http://www.nagiosexchange.org/Communication.41.0.html?&tx_netnagext_pi1 [p_view]=140 [[Scrip|http://www.nagiosexchange.org/Communication.41.0.html]]?&amp;tx_netnagext_pi1[p_view]=140] daemon running on the Nagios server.<br />
<br />
Condition: User Defined<br />
<br />
Custom Condition:<br />
<br />
if ($self->TransactionObj->Type eq 'Create' ||<br />
$self->TransactionObj->Type eq 'Status' ||<br />
($self->TransactionObj->Type eq 'Set' && $self->TransactionObj->Field eq "Queue")) {<br />
return(1);<br />
} else {<br />
return(undef);<br />
}<br />
<br />
Action: User Defined<br />
<br />
Custom action preparation code:<br />
<br />
1;<br />
<br />
Custom action cleanup code:<br />
<br />
{<br />
my %hosts = qw(<br />
Queue-Name1 definedNagiosHost1.domain.com<br />
Queue-Name2 definedNagiosHost2.domain.com<br />
);<br />
my $nscaBin = '/usr/local/nagios/libexec/send_nsca';<br />
my $nscaCfg = '/usr/local/nagios/etc/send_nsca.cfg';<br />
my $nscaHst = '<IP of nagios server>';<br />
<br />
foreach my $QueueName (keys %hosts) {<br />
my $hostname = $hosts{$QueueName};<br />
my $TicketsObj = RT::Tickets->new($RT::SystemUser);<br />
$TicketsObj->LimitStatus(VALUE => 'open');<br />
$TicketsObj->LimitStatus(VALUE => 'new');<br />
$TicketsObj->LimitQueue(VALUE => $QueueName);<br />
my $count = $TicketsObj->Count();<br />
if ($count eq '0') {<br />
system("printf \"$hostname\\t$QueueName\\t0\\t$QueueName: No Alerts\\n\" | $nscaBin -H $nscaHst -c $nscaCfg");<br />
} else {<br />
system("printf \"$hostname\\t$QueueName\\t2\\t$QueueName: Open Alert(s)\\n\" | $nscaBin -H $nscaHst -c $nscaCfg");<br />
}<br />
}<br />
1;<br />
}<br />
<br />
<br />
<br />
Template: Global Template: Blank<br />
<br />
See also: [[ManualScrips]], [[WriteCustomAction]], [[WriteCustomCondition]]</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=SendNagiosAlert&diff=26472SendNagiosAlert2017-01-08T22:34:55Z<p>Barton: </p>
<hr />
<div>Here's a [[Scrip]] that you can use to send an alert to [http://www.nagios.org Nagios] if a ticket is new or open in a particular [[Queue]](s). This scrip will only run if a ticket is created, a ticket's status is changed, or a ticket is moved to another queue. If one of these conditions is met, then it will looked at each queue defined in the scrip to see if there are any open or new [[Ticket]]s in those queues. If there are no tickets in that queue, it will send an OK to the corresponding nagios service. If there are new or open tickets in that queue, it will send a CRITICAL to the corresponding nagios alert.<br />
<br />
You must have Nagios already configured for this passive check, have send_nsca installed on the RT server, and the nsca [http://www.nagiosexchange.org/Communication.41.0.html?&tx_netnagext_pi1 [p_view]=140 [[Scrip|http://www.nagiosexchange.org/Communication.41.0.html]]?&amp;tx_netnagext_pi1[p_view]=140] daemon running on the Nagios server.<br />
<br />
Condition: User Defined<br />
<br />
Custom Condition:<br />
<br />
if ($self-&gt;TransactionObj-&gt;Type eq 'Create' ||<br />
$self-&gt;TransactionObj-&gt;Type eq 'Status' ||<br />
($self-&gt;TransactionObj-&gt;Type eq 'Set' &amp;&amp; $self-&gt;TransactionObj-&gt;Field eq "Queue")) {<br />
return(1);<br />
} else {<br />
return(undef);<br />
}<br />
<br />
<br />
Action: User Defined<br />
<br />
Custom action preparation code:<br />
<br />
1;<br />
<br />
Custom action cleanup code:<br />
<br />
{<br />
my %hosts = qw(<br />
Queue-Name1 definedNagiosHost1.domain.com<br />
Queue-Name2 definedNagiosHost2.domain.com<br />
);<br />
my $nscaBin = '/usr/local/nagios/libexec/send_nsca';<br />
my $nscaCfg = '/usr/local/nagios/etc/send_nsca.cfg';<br />
my $nscaHst = '&lt;IP of nagios server&gt;';<br />
<br />
foreach my $QueueName (keys %hosts) {<br />
my $hostname = $hosts{$QueueName};<br />
my $TicketsObj = RT::Tickets-&gt;new($RT::SystemUser);<br />
$TicketsObj-&gt;LimitStatus(VALUE =&gt; 'open');<br />
$TicketsObj-&gt;LimitStatus(VALUE =&gt; 'new');<br />
$TicketsObj-&gt;LimitQueue(VALUE =&gt; $QueueName);<br />
my $count = $TicketsObj-&gt;Count();<br />
if ($count eq '0') {<br />
system("printf \"$hostname\\t$QueueName\\t0\\t$QueueName: No Alerts\\n\" | $nscaBin -H $nscaHst -c $nscaCfg");<br />
} else {<br />
system("printf \"$hostname\\t$QueueName\\t2\\t$QueueName: Open Alert(s)\\n\" | $nscaBin -H $nscaHst -c $nscaCfg");<br />
}<br />
}<br />
1;<br />
}<br />
<br />
<br />
Template: Global Template: Blank<br />
<br />
See also: [[ManualScrips]], [[WriteCustomAction]], [[WriteCustomCondition]]</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=ScripAction&diff=26471ScripAction2017-01-08T22:23:12Z<p>Barton: /* Adding new actions */</p>
<hr />
<div>'''ScripAction''' - is Perl code formed as module or filled in [[CustomActionPreparationCode]] and [[CustomActionCleanupCode]] [[Scrip]] fields.<br />
<br />
This code applied after [[Condition]] check when [[Transaction]] is applicable.<br />
<br />
A '''ScripAction''' can access and change the current instance of the following objects:<br />
<br />
* [[Scrip]]<br />
* [[Ticket]]<br />
* [[Transaction]]<br />
* [[Template]]<br />
<br />
Note that Per-Transaction custom fields values are not available to ScripActions, (RT sets these after the Scrip has been executed) unless you change the Global Scrip Stage from Normal to Batch in the Applies to Page for your Scrip (as described in [[TransactionBatchStage]] .) If your Scrip is set to Batch then it will be run after all the Transactions have been created.<br />
<br />
Some of the built-in actions are:<br />
<br />
* Autoreply - emails the requestor<br />
* Notify and NotifyAsComment - emails the correspondance to ticket recipients<br />
* CreateTickets - creates one or more tickets according to the specified template<br />
<br />
== Adding new actions ==<br />
<br />
If you want to add additional built-in '''ScripActions''' you can do so by manually inserting rows into the '''ScripActions''' table. For example, to add a new Scrip Action for notifying [[Owner]] and [[AdminCC]]s, you can use this INSERT statement in [[MySQL]]:<br />
<br />
INSERT Into ScripActions(<br />
Name, Description, ExecModule, Argument, Creator, Created, LastUpdatedBy, LastUpdated<br />
) VALUES (<br />
'Notify Owner and AdminCcs', 'Sends mail to the Owner and AdminCcs', 'Notify', 'Owner,AdminCc', 1, NOW(), 1, NOW()<br />
);<br />
<br />
Another nice one is to avoid sending duplicate mails to Ccs who get explicitly Cced by someone who doesn't realize they'll get a copy.<br />
<br />
INSERT Into ScripActions(<br />
Name, Description, ExecModule, Argument, Creator, Created, LastUpdatedBy, LastUpdated<br />
) VALUES (<br />
'Notify Requestors, Ccs &amp; Other Recipients', 'Sends mail to the Ticket Requestor and Ccs, and explicitly listed Ccs and Bccs', 'Notify', 'Requestor,Cc,OtherRecipients', 1, NOW(), 1, NOW()<br />
);<br />
<br />
The important columns are '''ExecModule''' and '''Argument'''. The '''ExecModule''' names the module that will perform the action. These all have the name prefix "RT::Action::". Therefore, in the above example, the module used to perform the Scrip Action is named "RT::Action::Notify". Possible actions include:<br />
<br />
* AutoOpen - set the ticket status to open<br />
* Autoreply - send an auto-reply to the requestor<br />
* CreateTickets - create a ticket or tickets based upon the template<br />
* NotifyAsComment - send a comment to the recipients in '''Argument'''<br />
* Notify - send a comment to the recipients in '''Argument'''<br />
* UserDefined - execute the custom action code<br />
<br />
Full list of available modules for actions you can find in the <code>lib/RT/Action/</code> dir. Each module has inlined documentation, you can read it with [[perldoc]] utility, for example [=perldoc lib/RT/Action/[[AutoOpen]].pm].<br />
<br />
Values of the '''Argument''' field are different for different modules. Many modules have no description of the format that must be used, in such a case ask on the [[MailingLists]] and then when you'll figure that out, please, send a patch to the rt developers team.<br />
<br />
See also [[SendEmailAction]] (todo: integrate)<br />
<br />
== Managing notification actions ==<br />
<br />
A common user problem is that RT sends two (or more) notifications if a user is in two recipients lists at the same time, for example in both the [[CC]]s and [[Requestor]]s lists. This happens when you have '''two''' scrips one with Action 'Notify Cc' and another with 'notify requestors'. RT by default has several complex combinations, for example 'Notify Requestors, Ccs and AdminCcs'. When there is no required combination of recipients you can create your own.<br />
<br />
The '''Argument''' for Autoreply, NotifyAsComment, and Notify should be the name of a recipient. The following recipients are possible.<br />
<br />
* [[Requestor]] - the person or persons making the request<br />
* [[Owner]] - the owner of the request<br />
* [[?CC|Cc]] - all the Ccs set on the ticket<br />
* [[?AdminCC|AdminCc]] - all the AdminCcs set on the ticket<br />
* All - this is the same as "[=Requestor,Owner,Cc,[[AdminCc]]]"<br />
* OtherRecipients - the Ccs and Bccs set on the transaction<br />
<br />
You can also use any combination of the above by separating multiple recipients by a comma without whitespace. For example, "<code>Requestor,Owner</code>" would send to requestors and owners. See the example of INSERT query above.<br />
<br />
See also [[SendEmailAction]] (todo: integrate)<br />
<br />
== See also ==<br />
<br />
[[Contributions]], [[WriteCustomAction]]</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=CcManagers&diff=26470CcManagers2017-01-08T22:07:57Z<p>Barton: /* Install script */</p>
<hr />
<div>= Overview =<br />
If you have a similar group structure like the one defined in [[Rights|rights]] (see section departments of a company as groups), you might need that the users of each departments are not able to see the tickets of the queues and that managers of those departments can do. If creating a queue for each group is not an option, keep reading.<br />
<br />
Note that I habe been using RT for over a week now; this is my very first custom action, so there might be ways of improving it.<br />
<br />
--[[User:Gmirandaupc|Gmirandaupc]] 10:50, December 13, 2010 (UTC)<br />
<br />
= Custom action code =<br />
== Parameters ==<br />
The code assumes that there is a top-level group that must be passed as a parameter (in the installation script). I call that group 'Customers', although it could be just 'Departments'. There is also a hardcoded value, the suffix of the manager groups. Each department group with managers must have a subgroup whose name is the name of the parent group succeeded by 'Mgr'.<br />
<br />
Sample structure:<br />
* Customers<br />
** OrderDept<br />
*** OrderDeptMgr<br />
** TeacherDept<br />
*** TeacherDeptMgr<br />
<br />
== Install script ==<br />
# To install, install CcManagers.pm in local/lib/RT/Action, and<br />
# this script in local/etc/CcManagers.install<br />
# /opt/rt3/sbin/rt-setup-database --action insert \<br />
# --datafile /opt/rt3/local/etc/CcManagers.install<br />
#<br />
<br />
<br />
@ScripActions = (<br />
{<br />
Name => 'On Create Add Manager Group CC',<br />
Description => 'When a ticket is created, if the user belongs to a group under a predefined parent group (the argument), the manager subgroup will be added as Cc.',<br />
ExecModule => 'CcManagers',<br />
Argument => 'Customers'<br />
},<br />
);<br />
<br />
== Code ==<br />
Save the following code to the local action lib dir (i.e. /opt/rt3/local/lib/RT/Action) as CcManagers.pm<br />
<pre><br />
#<br />
# This custom action sets the users of the manager group of the ESSI or LSI<br />
# departments as CC of the ticket, depending on the group of the user that<br />
# created the ticket.<br />
#<br />
# @author Guillermo Miranda Álamo - LCLSI UPC <gmiranda@lsi.upc.edu><br />
# @date 09/12/2010 (dd/mm/yyyy).<br />
#<br />
<br />
package RT::Action::CcManagers;<br />
use base qw(RT::Action::Generic);<br />
<br />
use RT::Groups;<br />
<br />
my $actionDesc = "On Create Add Manager Group CC";<br />
<br />
<br />
=head2 Prepare<br />
<br />
When the ticket is created, if the user is in a group (or more) of 'Customers'<br />
(note that 'Customers' is the argument), the manager subgroup of that group<br />
will be added as Cc.<br />
<br />
It is mandatory that the managers subgroup are named with a suffix "Mgr".<br />
So if the group name is "TestingDept", the managers must be in "TestingDeptMgr",<br />
a subgroup of "TestingDept".<br />
<br />
=cut<br />
<br />
sub Prepare {<br />
my $self = shift;<br />
<br />
$RT::Logger->debug( "[" . $actionDesc . "] Custom action prep init. Argument is " . $self->Argument );<br />
<br />
my $ticket = $self->TicketObj;<br />
my $transaction = $self->TransactionObj;<br />
#my $owner = $ticket->OwnerObj; #nobody<br />
my $owner = RT::User->new( $RT::SystemUser );<br />
$owner->Load( $transaction->Creator );<br />
my $queue = $ticket->QueueObj;<br />
<br />
# Change this, it should be a user-defined value<br />
my $managerSuffix = "Mgr"; # The suffix of the name of every manager group<br />
my $parentGroupName = $self->Argument; # The name of the parent group of all the departments<br />
<br />
my $parentGroupObj = RT::Group->new( $RT::SystemUser );<br />
$parentGroupObj->LoadUserDefinedGroup( $parentGroupName );<br />
<br />
return undef unless $parentGroupObj;<br />
<br />
my $ownerGroups = RT::Groups->new( $RT::SystemUser );<br />
#$ownerGroups->LimitToRolesForQueue( $queue->Id ); # Doesn't seem to work<br />
$ownerGroups->LimitToUserDefinedGroups();<br />
$ownerGroups->UnLimit();<br />
<br />
# For each group<br />
while( my $ownerGroup = $ownerGroups->Next() ){<br />
# If it's a department and the user is in that department<br />
if( $parentGroupObj->HasMember( $ownerGroup->Id ) ){<br />
$RT::Logger->info( "[" . $actionDesc . "] Checking group '"<br />
. $ownerGroup->Name . "' (" . $ownerGroup->Id . ") for user "<br />
. $owner->Name . "-" . $owner->PrincipalId );<br />
<br />
if( $ownerGroup->HasMember( $owner->Id ) ){<br />
$RT::Logger->info( "[" . $actionDesc . "] User is member of '" <br />
. $ownerGroup->Name . "' (" . $ownerGroup->Id . ")" );<br />
<br />
# This action will be performed for each dept the user belongs to<br />
my $groupName = $ownerGroup->Name . $managerSuffix;<br />
<br />
# $RT::Logger->info( "[" . $actionDesc . "] Manager group name should be " . $groupName );<br />
# Retrieve the group<br />
my $groupObj = RT::Group->new( $RT::SystemUser );<br />
<br />
$groupObj->LoadUserDefinedGroup( $groupName );<br />
# If the group doesn't have a manager subgroup, skip<br />
if( !$groupObj ){<br />
next;<br />
}<br />
<br />
$RT::Logger->debug( "[" . $actionDesc . "] Adding '" . $groupName ."'(" . $groupObj->Id . ") to ticket \#" .$ticket->id );<br />
<br />
# Add the group (as a group, not every user of the group) as Cc<br />
$ticket->AddWatcher( Type => 'Cc',<br />
PrincipalId => $groupObj->PrincipalId );<br />
}<br />
}<br />
}<br />
<br />
return 1;<br />
}<br />
<br />
sub Commit{<br />
my $self = shift;<br />
<br />
return 1;<br />
}<br />
<br />
1;<br />
<br />
</pre><br />
<br />
You can use the following install script<br />
<br />
= Scrip creation =<br />
Condition: Create<br />
Action: On Create Add Manager Group Cc<br />
Template: Global template: Blank<br />
Stage: TransactionCreate<br />
<br />
= Credits =<br />
This custom action is based on the code of [[OnCreateAddGroupCc]] and [[OnCreateSetDeptHeadCc]].</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=InactiveStatus&diff=26469InactiveStatus2017-01-08T21:56:34Z<p>Barton: </p>
<hr />
<div>Inactive status are specified in RT configuration file with @[[InactiveStatus]].<br />
<br />
The default setting is:<br />
<br />
Set(@[[InactiveStatus]], qw(resolved rejected deleted));<br />
<br />
See also: [[ActiveStatus]].<br />
<br />
[[CustomStatuses]] for RT 3.8 and under<br />
<br />
[[CustomStatusesInRt4]] for RT 4 and over</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=DueDateRemindersByEmail&diff=26468DueDateRemindersByEmail2017-01-08T20:52:57Z<p>Barton: </p>
<hr />
<div>The following script will send email notifications on Tickets that are over due.<br />
<br />
Notes by [[User:Barton|Barton]]: I ran this page through a [[lowHangingFruit#sed_script_to_clean_up_nowiki_tagged_code|sed script]] that fixed the formatting of the nowiki formatted code blocks. You are encouraged to check the history of this page and make sure that I didn't mess anything up.<br />
<br />
== New version ( 3.1 ) ==<br />
<br />
====== New version ( 3.1 ) by Vaclav Vobornik added at 4.7.2008 ======<br />
<br />
i made a cleaned version be subsituting &lt; and &gt; to < and >. this apperently got lost while moving from wikia to here.<br />
<br />
also the preformatted text block syntax nowiki used below does not work here yet :(<br />
<br />
find it here: http://pastebin.com/gj5R7wm2<br />
<br />
####################### RT Email Notification Script ####################<br />
####<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Date: 05/06/05<br />
####<br />
#### Modified by: Tomas Borland Valenta<br />
#### Email: tomas at trustica dot cz<br />
#### Date: 2007/03/12<br />
####<br />
#### Modified by: Tim Schaller<br />
#### Email: tim-rt@torzo.com<br />
#### Date: 2008/06/17<br />
####<br />
#### Modified by: Vaclav Vobornik<br />
#### Email: vaclav dot vobornik at commerzbank dot com<br />
#### Date: 2008/07/04<br />
####<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
####<br />
#### Version: 3.1<br />
####<br />
#### Changes from 3 ( Vaclav Vobornik )<br />
#### - Added Cc and Bcc possibilities.<br />
####<br />
#### Changes from 2 ( Tim Schaller )<br />
#### - Added multiple command line options.<br />
#### - Adaptive subject line.<br />
#### - Sending Admin CC emails optional.<br />
####<br />
#### Changes from 1.2 ( Tomas Borland Valenta )<br />
#### - rewriten mail subsystem<br />
#### - code cleanup<br />
#### - adopted for RT 3.6.x<br />
#### - used some global RT config variables<br />
####<br />
#### ======================================================================<br />
####<br />
#### Command line options<br />
#### -d : turns dubugging on<br />
#### -A : Send to AdminCC ( made default not to )<br />
#### -a <n> : Send reminders to tickets due in <n> or less days.<br />
#### : Includes overdue tickets.<br />
#### -q <queue> : Only send reminder for tickets in <queue><br />
#### -o <owner> : Only send reminders for tickets owned by <owner><br />
#### -c <email> : Email in Cc<br />
#### -b <email> : Email in Bcc<br />
####<br />
#### ======================================================================<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### : Remind them about tickets due in less then 5 days.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -a 5 -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue.<br />
#### : Send copies to all AdminCC on the tickest.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A -q SysAdmin<br />
<br />
### External libraries ###<br />
use strict;<br />
use Getopt::Std;<br />
<br />
use lib ("/opt/rt3/lib"); # Change this to your RT lib path!<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
<br />
################## Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
# Set config variables<br />
my $debug=0;<br />
my $from_address = $RT::CorrespondAddress; #From: address used in reports<br />
my $rt_url = $RT::WebURL;<br />
my $sendmail = "$RT::SendmailPath $RT::SendmailArguments";<br />
<br />
################## Args ##################<br />
my $queue = '';<br />
my $owner = '';<br />
my $advDate = 0;<br />
my $secInDay = 60*60*24;<br />
my $sendToAdminCC = 0;<br />
my $cc = '';<br />
my $bcc = '';<br />
<br />
my %options=();<br />
Getopt::Std::getopts("Ada:q:o:c:b:",\%options);<br />
<br />
$queue = $options{q} if defined $options{q};<br />
$owner = $options{o} if defined $options{o};<br />
$advDate = ( $options{a} * $secInDay ) if defined $options{a};<br />
$debug = $options{d} if defined $options{d};<br />
$sendToAdminCC = $options{A} if defined $options{A};<br />
$cc = $options{c} if defined $options{c};<br />
$bcc = $options{b} if defined $options{b};<br />
<br />
<br />
################## Variables Init ##################<br />
my $User = new RT::User($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my $report; # Used for output<br />
my $subject; # Used as subject line<br />
<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix < (1 - $advDate ) or $date->Unix == -1 or $date->Unix == 0) { next; }<br />
<br />
# Compare owner and queue if given. Skip current ticket if invalid.<br />
if ($owner) { if ( lc($User->Name) ne lc($owner) ) { next; } }<br />
if ($queue) { if ( lc($Ticket->QueueObj->Name) ne lc($queue) ) { next; } }<br />
<br />
# Generate a report<br />
$report = "";<br />
$report .= "Ticket #: " . $Ticket->id . "\n";<br />
$report .= "Subject: " . $Ticket->Subject . "\n";<br />
$report .= "Queue: " . $Ticket->QueueObj->Name . " (". $Ticket->QueueObj->AdminCcAddresses .") \n";<br />
$report .= "Owner: " . $User->Name ."\n";<br />
$report .= "Due date: " . $date->ISO . "\n";<br />
$report .= "URL: " . $rt_url . "Ticket/Display.html?id=" . $Ticket->id . "\n";<br />
<br />
# Set the subject based on the due date.<br />
if( ($now->Unix - $date->Unix < 0 ) or $date->Unix == -1 ) {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is due on " . $date->ISO;<br />
} else {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is overdue";<br />
}<br />
<br />
# Get Queue Admin CC<br />
# Do we send to Admin CC as well as to owner?<br />
my @emails = ();<br />
if ( $sendToAdminCC ) {<br />
@emails = ($User->EmailAddress, split(/,/, $Ticket->AdminCcAddresses), split(/,/ , $Ticket->QueueObj->AdminCcAddresses));<br />
} else {<br />
@emails = ($User->EmailAddress);<br />
}<br />
<br />
# remove duplicates<br />
my %temp = (); @emails = grep ++$temp{$_} < 2, @emails;<br />
send_report(@emails);<br />
}<br />
<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
# This procedure will send a report by mail to the owner<br />
# parameter 1 - email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $from_address - address to send from<br />
# $cc - CarbonCoby email address<br />
# $bcc - BlindCarbonCopy email address<br />
sub send_report {<br />
my @tos = @_;<br />
my $addr;<br />
<br />
foreach $addr (@tos) {<br />
next if (length($addr) == 0);<br />
my $msg = "";<br />
$msg .= "From: $from_address\n";<br />
$msg .= "To: $addr\n";<br />
$msg .= "Cc: $cc\n" if $cc;<br />
$msg .= "Bcc: $bcc\n" if $bcc;<br />
$msg .= "Subject: $subject\n";<br />
$msg .= "\n";<br />
$msg .= $report;<br />
<br />
if ($debug) {<br />
print "====== Would call '$sendmail' with this input:\n";<br />
print "$msg\n\n";<br />
} else {<br />
open(SENDMAIL, "|$sendmail") || die "Error sending mail: $!";<br />
print SENDMAIL $msg;<br />
close(SENDMAIL);<br />
}<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
== Old version ( 3.0 ) ==<br />
<br />
====== Version ( 3.0 ) by Tim Schaller added at 17.6.2008 ======<br />
<br />
####################### RT Email Notification Script ####################<br />
####<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Date: 05/06/05<br />
####<br />
#### Modified by: Tomas Borland Valenta<br />
#### Email: tomas at trustica dot cz<br />
#### Date: 2007/03/12<br />
####<br />
#### Modified by: Tim Schaller<br />
#### Email: tim-rt@torzo.com<br />
#### Date: 2008/06/17<br />
####<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
####<br />
#### Version: 3<br />
####<br />
#### Changes from 2 ( Tim Schaller )<br />
#### - Added multiple command line options.<br />
#### - Adaptive subject line.<br />
#### - Sending Admin CC emails optional.<br />
####<br />
#### Changes from 1.2 ( Tomas Borland Valenta )<br />
#### - rewriten mail subsystem<br />
#### - code cleanup<br />
#### - adopted for RT 3.6.x<br />
#### - used some global RT config variables<br />
####<br />
#### ======================================================================<br />
####<br />
#### Command line options<br />
#### -d : turns dubugging on<br />
#### -A : Send to AdminCC ( made default not to )<br />
#### -a <n> : Send reminders to tickets due in <n> or less days.<br />
#### : Includes overdue tickets.<br />
#### -q <queue> : Only send reminder for tickets in <queue><br />
#### -o <owner> : Only send reminders for tickets owned by <owner><br />
####<br />
#### ======================================================================<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### : Remind them about tickets due in less then 5 days.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -a 5 -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue.<br />
#### : Send copies to all AdminCC on the tickest.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A -q SysAdmin<br />
<br />
### External libraries ###<br />
use strict;<br />
use Getopt::Std;<br />
<br />
use lib ("/usr/local/rt/lib"); # Change this to your RT lib path!<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
<br />
################## Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
# Set config variables<br />
my $debug=0;<br />
my $from_address = $RT::CorrespondAddress; #From: address used in reports<br />
my $rt_url = $RT::WebURL;<br />
my $sendmail = "$RT::SendmailPath $RT::SendmailArguments";<br />
<br />
################## Args ##################<br />
my $queue = '';<br />
my $owner = '';<br />
my $advDate = 0;<br />
my $secInDay = 60*60*24;<br />
my $sendToAdminCC = 0;<br />
<br />
my %options=();<br />
Getopt::Std::getopts("Ada:q:o:",\%options);<br />
<br />
$queue = $options{q} if defined $options{q};<br />
$owner = $options{o} if defined $options{o};<br />
$advDate = ( $options{a} * $secInDay ) if defined $options{a};<br />
$debug = $options{d} if defined $options{d};<br />
$sendToAdminCC = $options{A} if defined $options{A};<br />
<br />
################## Variables Init ##################<br />
my $User = new RT::User($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my $report; # Used for output<br />
my $subject; # Used as subject line<br />
<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix < (1 - $advDate ) or $date->Unix == -1) { next; }<br />
<br />
# Compare owner and queue if given. Skip current ticket if invalid.<br />
if ($owner) { if ( lc($User->Name) ne lc($owner) ) { next; } }<br />
if ($queue) { if ( lc($Ticket->QueueObj->Name) ne lc($queue) ) { next; } }<br />
<br />
# Generate a report<br />
$report = "";<br />
$report .= "Ticket #: " . $Ticket->id . "\n";<br />
$report .= "Subject: " . $Ticket->Subject . "\n";<br />
$report .= "Queue: " . $Ticket->QueueObj->Name . " (". $Ticket->QueueObj->AdminCcAddresses .") \n";<br />
$report .= "Owner: " . $User->Name ."\n";<br />
$report .= "Due date: " . $date->ISO . "\n";<br />
$report .= "URL: " . $rt_url . "Ticket/Display.html?id=" . $Ticket->id . "\n";<br />
<br />
# Set the subject based on the due date.<br />
if( ($now->Unix - $date->Unix < 0 ) or $date->Unix == -1 ) {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is due on " . $date->ISO;<br />
} else {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is overdue";<br />
}<br />
<br />
# Do we send to Admin CC as well as to owner?<br />
my @emails = ();<br />
if ( $sendToAdminCC ) {<br />
@emails = ($User->EmailAddress, split(/,/, $Ticket->AdminCcAddresses), split(/,/ , $Ticket->QueueObj->AdminCcAddresses));<br />
} else {<br />
@emails = ($User->EmailAddress);<br />
}<br />
<br />
# remove duplicates<br />
my %temp = (); @emails = grep ++$temp{$_} < 2, @emails;<br />
send_report(@emails);<br />
}<br />
<br />
<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
# This procedure will send a report by mail to the owner<br />
# parameter 1 - email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $from_address - address to send from<br />
sub send_report {<br />
my @tos = @_;<br />
my $addr;<br />
<br />
foreach $addr (@tos) {<br />
next if (length($addr) == 0);<br />
my $msg = "";<br />
$msg .= "From: $from_address\n";<br />
$msg .= "To: $addr\n";<br />
$msg .= "Subject: $subject\n";<br />
$msg .= "\n";<br />
$msg .= $report;<br />
<br />
if ($debug) {<br />
print "====== Would call '$sendmail' with this input:\n";<br />
print "$msg\n\n";<br />
} else {<br />
open(SENDMAIL, "|$sendmail") || die "Error sending mail: $!";<br />
print SENDMAIL $msg;<br />
close(SENDMAIL);<br />
}<br />
}<br />
}<br />
<br />
<br />
<br />
== Old version ==<br />
<br />
====== Version by Tomas Borland Valenta added at 14.3.2007 ======<br />
<br />
####################### RT Email Notification Script ####################<br />
####<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Date: 05/06/05<br />
####<br />
#### Modified by: Tomas Borland Valenta<br />
#### Email: tomas at trustica dot cz<br />
#### Date: 2007/03/12<br />
####<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
####<br />
#### Version: 2<br />
#### Changes from 1.2<br />
#### - rewriten mail subsystem<br />
#### - code cleanup<br />
#### - adopted for RT 3.6.x<br />
#### - used some global RT config variables<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl<br />
<br />
### External libraries ###<br />
use strict;<br />
use lib ("/usr/share/request-tracker3.6/lib");<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
<br />
################## Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
# Set config variables<br />
my $debug=0;<br />
my $from_address = $RT::CorrespondAddress; #From: address used in reports<br />
my $rt_url = $RT::WebURL;<br />
my $sendmail = "$RT::SendmailPath $RT::SendmailArguments";<br />
<br />
################## Variables Init ##################<br />
my $User = new RT::User($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my $report; # Used for output<br />
my $subject; # Used as subject line<br />
<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix < 0 or $date->Unix == -1) { next; }<br />
# Generate a report<br />
$report = "";<br />
$report .= "Ticket #: " . $Ticket->id . "\n";<br />
$report .= "Subject: " . $Ticket->Subject . "\n";<br />
$report .= "Queue: " . $Ticket->QueueObj->Name . " (". $Ticket->QueueObj->AdminCcAddresses .") \n";<br />
$report .= "Owner: " . $User->Name ."\n";<br />
$report .= "Due date: " . $date->ISO . "\n";<br />
$report .= "URL: " . $rt_url . "Ticket/Display.html?id=" . $Ticket->id . "\n";<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is overdue";<br />
<br />
# Get Queue Admin CC<br />
my @emails = ($User->EmailAddress, split(/,/, $Ticket->AdminCcAddresses), split(/,/ , $Ticket->QueueObj->AdminCcAddresses));<br />
my %temp = (); @emails = grep ++$temp{$_} < 2, @emails; # remove duplicates<br />
send_report(@emails);<br />
}<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
# This procedure will send a report by mail to the owner<br />
# parameter 1 - email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $from_address - address to send from<br />
sub send_report {<br />
my @tos = @_;<br />
my $addr;<br />
<br />
foreach $addr (@tos) {<br />
next if (length($addr) == 0);<br />
my $msg = "";<br />
$msg .= "From: $from_address\n";<br />
$msg .= "To: $addr\n";<br />
$msg .= "Subject: $subject\n";<br />
$msg .= "\n";<br />
$msg .= $report;<br />
if ($debug) {<br />
print "====== Would call '$sendmail' with this input:\n";<br />
print "$msg\n\n";<br />
} else {<br />
open(SENDMAIL, "|$sendmail") || die "Error sending mail: $!";<br />
print SENDMAIL $msg;<br />
close(SENDMAIL);<br />
}<br />
}<br />
}<br />
<br />
<br />
== Old version ==<br />
<br />
====== Daniely Yoav, !QBall Technologies Ltd. yoavd![at]qballtech![dot]net ======<br />
<br />
You can cut/paste or download the script from [http://qballtech.net/rt_3_remind_email_due.pl.gz Notifications script]. Put the script in your daily crontab (/etc/cron.daily on Fedora Core)<br />
<br />
####################### RT Email Notification Script ####################<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
#### Version: 1.1<br />
#### Usage: Invoke via cron<br />
#### */5 * * * * /path/to/script/remind_email_due.pl<br />
#### Date: 05/06/05<br />
############################################################<br />
my $from_address = 'reports@demo.qballtech.net'; #From: address used in reports<br />
my $mail_host = 'localhost'; #Mail Server used for sending mail<br />
my $my_host = 'demo.qballtech.net'; # My FQDN<br />
my $rt_url = 'https://demo.qballtech.net/rt';<br />
<br />
# Days to send notifcations on<br />
# Enable Debug<br />
my $debug=0;<br />
# initalize<br />
use lib ("/usr/local/rt3/lib", "/usr/local/rt3/local/lib");<br />
############################################################<br />
################## DO NOT EDIT BELOW THIS LINE ##################<br />
################## External dependancies ##################<br />
use strict;<br />
use Carp;<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
use Mail::Internet;<br />
use Mail::Address;<br />
use Net::SMTP;<br />
use Encode;<br />
use MIME::Base64;<br />
use MIME::QuotedPrint;<br />
use MIME::Words qw(:all);<br />
<br />
################## RT Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
################## Variables Init ##################<br />
my $User = RT::User->new($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $pipe; # Used as PIPE to transfer data to smbclient<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my @report; # Used for output<br />
my $subject; # Used as subject line<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix > 0 and $date->Unix != -1) {<br />
# Generate a report<br />
@report = ();<br />
push (@report,"Ticket #" . $Ticket->id . " is over his due date. \n");<br />
push (@report,"Owner: " . $User->Name ."\n");<br />
push (@report,"Due date:" . $date->ISO . "\n");<br />
push (@report,"Subject: " . $Ticket->Subject . "\n");<br />
push (@report,"URL: " . $rt_url . "/Ticket/Display.html?id=" . $Ticket->id . "\n");<br />
push (@report,"\n\nTickets notifications script by Qball Solutions");<br />
push (@report,"\nplease report problems to solutions\@helpdesk.qballtech.net)");<br />
push(@report,"\nContact us! (info\@qballtech.net)\n");<br />
$subject = "Ticket #". $Ticket->id . " with Owner: " . $User->Name ." is over his due date\n";<br />
#print $line . "\n";<br />
#print $User->EmailAddress . "\n";<br />
# Send report by email<br />
# Get Queue Admin CC<br />
send_report($User->EmailAddress . "," . $Ticket->AdminCcAddresses . "," .$Ticket->QueueObj->AdminCcAddresses);<br />
print @report if $debug;<br />
}<br />
}<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
sub send_report {<br />
##########################<br />
# Send report procedure###<br />
##########################<br />
# This procedure will send a report by mail to the owner<br />
# Parameter 1) Email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $mail_host - mail relay host address<br />
# $from_address - address to send from<br />
my $smtp;<br />
my $addr;<br />
my $full;<br />
my $to_address = "$_[0]";<br />
my @addrs = Mail::Address->parse("$to_address");<br />
my $mime_type = 'TEXT';<br />
my $message = @report;<br />
foreach $addr (@addrs)<br />
{<br />
$full=$addr->format;<br />
$smtp = Net::SMTP->new($mail_host,Debug=> 0);<br />
die "Couldn't connect to server" unless $smtp;<br />
$smtp->mail( $from_address );<br />
$smtp->to($full);<br />
$smtp->data();<br />
$smtp->datasend("Subject: $subject");<br />
$smtp->datasend("To: " . $full . "\n");<br />
$smtp->datasend("From: " . $from_address . "\n");<br />
$smtp->datasend("\n");<br />
$smtp->datasend("@report\n");<br />
<br />
$smtp->dataend();<br />
$smtp->quit();<br />
};<br />
}</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=LowHangingFruit&diff=26467LowHangingFruit2017-01-08T20:49:14Z<p>Barton: </p>
<hr />
<div>== Low Hanging Fruit ==<br />
<br />
Code block cleanup<br />
<br />
The previous version of the rt-wiki used a single space indent, sometimes surrounded by <code>&lt;nowiki&gt;</code> tags to delimit code blocks. Media-wiki uses a four space indent to delimit code. The old style does not correctly format the first line of the code block.<br />
<br />
The four space indent also makes the code literal, so you don't have to add html entities for greather than and less than.<br />
<br />
Old:<br />
<br />
&lt;%INIT&gt;<br />
$$skip = 1 if $Transaction-&gt;Creator == $RT::SystemUser-&gt;id;<br />
&lt;/%INIT&gt;<br />
&lt;%ARGS&gt;<br />
$Transaction =&gt; undef<br />
$skip =&gt; undef<br />
&lt;/%ARGS&gt;<br />
<br />
New:<br />
<br />
<%INIT><br />
$$skip = 1 if $Transaction->Creator == $RT::SystemUser->id;<br />
</%INIT><br />
<%ARGS><br />
$Transaction => undef<br />
$skip => undef<br />
</%ARGS><br />
<br />
=== sed script to clean up nowiki tagged code ===<br />
<br />
Note that you will have to turn html entities back into their rendered forms. I recommend pasting the wiki text to a file (say, <code>/tmp/fix-nowiki.txt</code>) and running the folloiwing:<br />
<br />
sed '/^ <nowiki>/,/^ <\/nowiki>/{s/^ <nowiki>/ <nowiki>\n /;<br />
s/&lt;/</g;<br />
s/&gt;/>/g;<br />
s/^ / /;<br />
/nowiki>/d}' /tmp/fix-nowiki.txt</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=DueDateRemindersByEmail&diff=26466DueDateRemindersByEmail2017-01-08T20:43:27Z<p>Barton: </p>
<hr />
<div>The following script will send email notifications on Tickets that are over due.<br />
<br />
The following script will send email notifications on Tickets that are over due.<br />
<br />
Notes by [[User:Barton|Barton]]: I ran this page through a sed script that fixed the formatting of the nowiki formatted code blocks. You are encouraged to check the history of this page and make sure that I didn't mess anything up.<br />
<br />
== New version ( 3.1 ) ==<br />
<br />
====== New version ( 3.1 ) by Vaclav Vobornik added at 4.7.2008 ======<br />
<br />
i made a cleaned version be subsituting &lt; and &gt; to < and >. this apperently got lost while moving from wikia to here.<br />
<br />
also the preformatted text block syntax nowiki used below does not work here yet :(<br />
<br />
find it here: http://pastebin.com/gj5R7wm2<br />
<br />
####################### RT Email Notification Script ####################<br />
####<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Date: 05/06/05<br />
####<br />
#### Modified by: Tomas Borland Valenta<br />
#### Email: tomas at trustica dot cz<br />
#### Date: 2007/03/12<br />
####<br />
#### Modified by: Tim Schaller<br />
#### Email: tim-rt@torzo.com<br />
#### Date: 2008/06/17<br />
####<br />
#### Modified by: Vaclav Vobornik<br />
#### Email: vaclav dot vobornik at commerzbank dot com<br />
#### Date: 2008/07/04<br />
####<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
####<br />
#### Version: 3.1<br />
####<br />
#### Changes from 3 ( Vaclav Vobornik )<br />
#### - Added Cc and Bcc possibilities.<br />
####<br />
#### Changes from 2 ( Tim Schaller )<br />
#### - Added multiple command line options.<br />
#### - Adaptive subject line.<br />
#### - Sending Admin CC emails optional.<br />
####<br />
#### Changes from 1.2 ( Tomas Borland Valenta )<br />
#### - rewriten mail subsystem<br />
#### - code cleanup<br />
#### - adopted for RT 3.6.x<br />
#### - used some global RT config variables<br />
####<br />
#### ======================================================================<br />
####<br />
#### Command line options<br />
#### -d : turns dubugging on<br />
#### -A : Send to AdminCC ( made default not to )<br />
#### -a <n> : Send reminders to tickets due in <n> or less days.<br />
#### : Includes overdue tickets.<br />
#### -q <queue> : Only send reminder for tickets in <queue><br />
#### -o <owner> : Only send reminders for tickets owned by <owner><br />
#### -c <email> : Email in Cc<br />
#### -b <email> : Email in Bcc<br />
####<br />
#### ======================================================================<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### : Remind them about tickets due in less then 5 days.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -a 5 -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue.<br />
#### : Send copies to all AdminCC on the tickest.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A -q SysAdmin<br />
<br />
### External libraries ###<br />
use strict;<br />
use Getopt::Std;<br />
<br />
use lib ("/opt/rt3/lib"); # Change this to your RT lib path!<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
<br />
################## Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
# Set config variables<br />
my $debug=0;<br />
my $from_address = $RT::CorrespondAddress; #From: address used in reports<br />
my $rt_url = $RT::WebURL;<br />
my $sendmail = "$RT::SendmailPath $RT::SendmailArguments";<br />
<br />
################## Args ##################<br />
my $queue = '';<br />
my $owner = '';<br />
my $advDate = 0;<br />
my $secInDay = 60*60*24;<br />
my $sendToAdminCC = 0;<br />
my $cc = '';<br />
my $bcc = '';<br />
<br />
my %options=();<br />
Getopt::Std::getopts("Ada:q:o:c:b:",\%options);<br />
<br />
$queue = $options{q} if defined $options{q};<br />
$owner = $options{o} if defined $options{o};<br />
$advDate = ( $options{a} * $secInDay ) if defined $options{a};<br />
$debug = $options{d} if defined $options{d};<br />
$sendToAdminCC = $options{A} if defined $options{A};<br />
$cc = $options{c} if defined $options{c};<br />
$bcc = $options{b} if defined $options{b};<br />
<br />
<br />
################## Variables Init ##################<br />
my $User = new RT::User($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my $report; # Used for output<br />
my $subject; # Used as subject line<br />
<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix < (1 - $advDate ) or $date->Unix == -1 or $date->Unix == 0) { next; }<br />
<br />
# Compare owner and queue if given. Skip current ticket if invalid.<br />
if ($owner) { if ( lc($User->Name) ne lc($owner) ) { next; } }<br />
if ($queue) { if ( lc($Ticket->QueueObj->Name) ne lc($queue) ) { next; } }<br />
<br />
# Generate a report<br />
$report = "";<br />
$report .= "Ticket #: " . $Ticket->id . "\n";<br />
$report .= "Subject: " . $Ticket->Subject . "\n";<br />
$report .= "Queue: " . $Ticket->QueueObj->Name . " (". $Ticket->QueueObj->AdminCcAddresses .") \n";<br />
$report .= "Owner: " . $User->Name ."\n";<br />
$report .= "Due date: " . $date->ISO . "\n";<br />
$report .= "URL: " . $rt_url . "Ticket/Display.html?id=" . $Ticket->id . "\n";<br />
<br />
# Set the subject based on the due date.<br />
if( ($now->Unix - $date->Unix < 0 ) or $date->Unix == -1 ) {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is due on " . $date->ISO;<br />
} else {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is overdue";<br />
}<br />
<br />
# Get Queue Admin CC<br />
# Do we send to Admin CC as well as to owner?<br />
my @emails = ();<br />
if ( $sendToAdminCC ) {<br />
@emails = ($User->EmailAddress, split(/,/, $Ticket->AdminCcAddresses), split(/,/ , $Ticket->QueueObj->AdminCcAddresses));<br />
} else {<br />
@emails = ($User->EmailAddress);<br />
}<br />
<br />
# remove duplicates<br />
my %temp = (); @emails = grep ++$temp{$_} < 2, @emails;<br />
send_report(@emails);<br />
}<br />
<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
# This procedure will send a report by mail to the owner<br />
# parameter 1 - email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $from_address - address to send from<br />
# $cc - CarbonCoby email address<br />
# $bcc - BlindCarbonCopy email address<br />
sub send_report {<br />
my @tos = @_;<br />
my $addr;<br />
<br />
foreach $addr (@tos) {<br />
next if (length($addr) == 0);<br />
my $msg = "";<br />
$msg .= "From: $from_address\n";<br />
$msg .= "To: $addr\n";<br />
$msg .= "Cc: $cc\n" if $cc;<br />
$msg .= "Bcc: $bcc\n" if $bcc;<br />
$msg .= "Subject: $subject\n";<br />
$msg .= "\n";<br />
$msg .= $report;<br />
<br />
if ($debug) {<br />
print "====== Would call '$sendmail' with this input:\n";<br />
print "$msg\n\n";<br />
} else {<br />
open(SENDMAIL, "|$sendmail") || die "Error sending mail: $!";<br />
print SENDMAIL $msg;<br />
close(SENDMAIL);<br />
}<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
== Old version ( 3.0 ) ==<br />
<br />
====== Version ( 3.0 ) by Tim Schaller added at 17.6.2008 ======<br />
<br />
####################### RT Email Notification Script ####################<br />
####<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Date: 05/06/05<br />
####<br />
#### Modified by: Tomas Borland Valenta<br />
#### Email: tomas at trustica dot cz<br />
#### Date: 2007/03/12<br />
####<br />
#### Modified by: Tim Schaller<br />
#### Email: tim-rt@torzo.com<br />
#### Date: 2008/06/17<br />
####<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
####<br />
#### Version: 3<br />
####<br />
#### Changes from 2 ( Tim Schaller )<br />
#### - Added multiple command line options.<br />
#### - Adaptive subject line.<br />
#### - Sending Admin CC emails optional.<br />
####<br />
#### Changes from 1.2 ( Tomas Borland Valenta )<br />
#### - rewriten mail subsystem<br />
#### - code cleanup<br />
#### - adopted for RT 3.6.x<br />
#### - used some global RT config variables<br />
####<br />
#### ======================================================================<br />
####<br />
#### Command line options<br />
#### -d : turns dubugging on<br />
#### -A : Send to AdminCC ( made default not to )<br />
#### -a <n> : Send reminders to tickets due in <n> or less days.<br />
#### : Includes overdue tickets.<br />
#### -q <queue> : Only send reminder for tickets in <queue><br />
#### -o <owner> : Only send reminders for tickets owned by <owner><br />
####<br />
#### ======================================================================<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### : Remind them about tickets due in less then 5 days.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -a 5 -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue.<br />
#### : Send copies to all AdminCC on the tickest.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A -q SysAdmin<br />
<br />
### External libraries ###<br />
use strict;<br />
use Getopt::Std;<br />
<br />
use lib ("/usr/local/rt/lib"); # Change this to your RT lib path!<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
<br />
################## Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
# Set config variables<br />
my $debug=0;<br />
my $from_address = $RT::CorrespondAddress; #From: address used in reports<br />
my $rt_url = $RT::WebURL;<br />
my $sendmail = "$RT::SendmailPath $RT::SendmailArguments";<br />
<br />
################## Args ##################<br />
my $queue = '';<br />
my $owner = '';<br />
my $advDate = 0;<br />
my $secInDay = 60*60*24;<br />
my $sendToAdminCC = 0;<br />
<br />
my %options=();<br />
Getopt::Std::getopts("Ada:q:o:",\%options);<br />
<br />
$queue = $options{q} if defined $options{q};<br />
$owner = $options{o} if defined $options{o};<br />
$advDate = ( $options{a} * $secInDay ) if defined $options{a};<br />
$debug = $options{d} if defined $options{d};<br />
$sendToAdminCC = $options{A} if defined $options{A};<br />
<br />
################## Variables Init ##################<br />
my $User = new RT::User($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my $report; # Used for output<br />
my $subject; # Used as subject line<br />
<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix < (1 - $advDate ) or $date->Unix == -1) { next; }<br />
<br />
# Compare owner and queue if given. Skip current ticket if invalid.<br />
if ($owner) { if ( lc($User->Name) ne lc($owner) ) { next; } }<br />
if ($queue) { if ( lc($Ticket->QueueObj->Name) ne lc($queue) ) { next; } }<br />
<br />
# Generate a report<br />
$report = "";<br />
$report .= "Ticket #: " . $Ticket->id . "\n";<br />
$report .= "Subject: " . $Ticket->Subject . "\n";<br />
$report .= "Queue: " . $Ticket->QueueObj->Name . " (". $Ticket->QueueObj->AdminCcAddresses .") \n";<br />
$report .= "Owner: " . $User->Name ."\n";<br />
$report .= "Due date: " . $date->ISO . "\n";<br />
$report .= "URL: " . $rt_url . "Ticket/Display.html?id=" . $Ticket->id . "\n";<br />
<br />
# Set the subject based on the due date.<br />
if( ($now->Unix - $date->Unix < 0 ) or $date->Unix == -1 ) {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is due on " . $date->ISO;<br />
} else {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is overdue";<br />
}<br />
<br />
# Do we send to Admin CC as well as to owner?<br />
my @emails = ();<br />
if ( $sendToAdminCC ) {<br />
@emails = ($User->EmailAddress, split(/,/, $Ticket->AdminCcAddresses), split(/,/ , $Ticket->QueueObj->AdminCcAddresses));<br />
} else {<br />
@emails = ($User->EmailAddress);<br />
}<br />
<br />
# remove duplicates<br />
my %temp = (); @emails = grep ++$temp{$_} < 2, @emails;<br />
send_report(@emails);<br />
}<br />
<br />
<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
# This procedure will send a report by mail to the owner<br />
# parameter 1 - email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $from_address - address to send from<br />
sub send_report {<br />
my @tos = @_;<br />
my $addr;<br />
<br />
foreach $addr (@tos) {<br />
next if (length($addr) == 0);<br />
my $msg = "";<br />
$msg .= "From: $from_address\n";<br />
$msg .= "To: $addr\n";<br />
$msg .= "Subject: $subject\n";<br />
$msg .= "\n";<br />
$msg .= $report;<br />
<br />
if ($debug) {<br />
print "====== Would call '$sendmail' with this input:\n";<br />
print "$msg\n\n";<br />
} else {<br />
open(SENDMAIL, "|$sendmail") || die "Error sending mail: $!";<br />
print SENDMAIL $msg;<br />
close(SENDMAIL);<br />
}<br />
}<br />
}<br />
<br />
<br />
<br />
== Old version ==<br />
<br />
====== Version by Tomas Borland Valenta added at 14.3.2007 ======<br />
<br />
####################### RT Email Notification Script ####################<br />
####<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Date: 05/06/05<br />
####<br />
#### Modified by: Tomas Borland Valenta<br />
#### Email: tomas at trustica dot cz<br />
#### Date: 2007/03/12<br />
####<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
####<br />
#### Version: 2<br />
#### Changes from 1.2<br />
#### - rewriten mail subsystem<br />
#### - code cleanup<br />
#### - adopted for RT 3.6.x<br />
#### - used some global RT config variables<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl<br />
<br />
### External libraries ###<br />
use strict;<br />
use lib ("/usr/share/request-tracker3.6/lib");<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
<br />
################## Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
# Set config variables<br />
my $debug=0;<br />
my $from_address = $RT::CorrespondAddress; #From: address used in reports<br />
my $rt_url = $RT::WebURL;<br />
my $sendmail = "$RT::SendmailPath $RT::SendmailArguments";<br />
<br />
################## Variables Init ##################<br />
my $User = new RT::User($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my $report; # Used for output<br />
my $subject; # Used as subject line<br />
<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix < 0 or $date->Unix == -1) { next; }<br />
# Generate a report<br />
$report = "";<br />
$report .= "Ticket #: " . $Ticket->id . "\n";<br />
$report .= "Subject: " . $Ticket->Subject . "\n";<br />
$report .= "Queue: " . $Ticket->QueueObj->Name . " (". $Ticket->QueueObj->AdminCcAddresses .") \n";<br />
$report .= "Owner: " . $User->Name ."\n";<br />
$report .= "Due date: " . $date->ISO . "\n";<br />
$report .= "URL: " . $rt_url . "Ticket/Display.html?id=" . $Ticket->id . "\n";<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is overdue";<br />
<br />
# Get Queue Admin CC<br />
my @emails = ($User->EmailAddress, split(/,/, $Ticket->AdminCcAddresses), split(/,/ , $Ticket->QueueObj->AdminCcAddresses));<br />
my %temp = (); @emails = grep ++$temp{$_} < 2, @emails; # remove duplicates<br />
send_report(@emails);<br />
}<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
# This procedure will send a report by mail to the owner<br />
# parameter 1 - email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $from_address - address to send from<br />
sub send_report {<br />
my @tos = @_;<br />
my $addr;<br />
<br />
foreach $addr (@tos) {<br />
next if (length($addr) == 0);<br />
my $msg = "";<br />
$msg .= "From: $from_address\n";<br />
$msg .= "To: $addr\n";<br />
$msg .= "Subject: $subject\n";<br />
$msg .= "\n";<br />
$msg .= $report;<br />
if ($debug) {<br />
print "====== Would call '$sendmail' with this input:\n";<br />
print "$msg\n\n";<br />
} else {<br />
open(SENDMAIL, "|$sendmail") || die "Error sending mail: $!";<br />
print SENDMAIL $msg;<br />
close(SENDMAIL);<br />
}<br />
}<br />
}<br />
<br />
<br />
== Old version ==<br />
<br />
====== Daniely Yoav, !QBall Technologies Ltd. yoavd![at]qballtech![dot]net ======<br />
<br />
You can cut/paste or download the script from [http://qballtech.net/rt_3_remind_email_due.pl.gz Notifications script]. Put the script in your daily crontab (/etc/cron.daily on Fedora Core)<br />
<br />
####################### RT Email Notification Script ####################<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
#### Version: 1.1<br />
#### Usage: Invoke via cron<br />
#### */5 * * * * /path/to/script/remind_email_due.pl<br />
#### Date: 05/06/05<br />
############################################################<br />
my $from_address = 'reports@demo.qballtech.net'; #From: address used in reports<br />
my $mail_host = 'localhost'; #Mail Server used for sending mail<br />
my $my_host = 'demo.qballtech.net'; # My FQDN<br />
my $rt_url = 'https://demo.qballtech.net/rt';<br />
<br />
# Days to send notifcations on<br />
# Enable Debug<br />
my $debug=0;<br />
# initalize<br />
use lib ("/usr/local/rt3/lib", "/usr/local/rt3/local/lib");<br />
############################################################<br />
################## DO NOT EDIT BELOW THIS LINE ##################<br />
################## External dependancies ##################<br />
use strict;<br />
use Carp;<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
use Mail::Internet;<br />
use Mail::Address;<br />
use Net::SMTP;<br />
use Encode;<br />
use MIME::Base64;<br />
use MIME::QuotedPrint;<br />
use MIME::Words qw(:all);<br />
<br />
################## RT Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
################## Variables Init ##################<br />
my $User = RT::User->new($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $pipe; # Used as PIPE to transfer data to smbclient<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my @report; # Used for output<br />
my $subject; # Used as subject line<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix > 0 and $date->Unix != -1) {<br />
# Generate a report<br />
@report = ();<br />
push (@report,"Ticket #" . $Ticket->id . " is over his due date. \n");<br />
push (@report,"Owner: " . $User->Name ."\n");<br />
push (@report,"Due date:" . $date->ISO . "\n");<br />
push (@report,"Subject: " . $Ticket->Subject . "\n");<br />
push (@report,"URL: " . $rt_url . "/Ticket/Display.html?id=" . $Ticket->id . "\n");<br />
push (@report,"\n\nTickets notifications script by Qball Solutions");<br />
push (@report,"\nplease report problems to solutions\@helpdesk.qballtech.net)");<br />
push(@report,"\nContact us! (info\@qballtech.net)\n");<br />
$subject = "Ticket #". $Ticket->id . " with Owner: " . $User->Name ." is over his due date\n";<br />
#print $line . "\n";<br />
#print $User->EmailAddress . "\n";<br />
# Send report by email<br />
# Get Queue Admin CC<br />
send_report($User->EmailAddress . "," . $Ticket->AdminCcAddresses . "," .$Ticket->QueueObj->AdminCcAddresses);<br />
print @report if $debug;<br />
}<br />
}<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
sub send_report {<br />
##########################<br />
# Send report procedure###<br />
##########################<br />
# This procedure will send a report by mail to the owner<br />
# Parameter 1) Email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $mail_host - mail relay host address<br />
# $from_address - address to send from<br />
my $smtp;<br />
my $addr;<br />
my $full;<br />
my $to_address = "$_[0]";<br />
my @addrs = Mail::Address->parse("$to_address");<br />
my $mime_type = 'TEXT';<br />
my $message = @report;<br />
foreach $addr (@addrs)<br />
{<br />
$full=$addr->format;<br />
$smtp = Net::SMTP->new($mail_host,Debug=> 0);<br />
die "Couldn't connect to server" unless $smtp;<br />
$smtp->mail( $from_address );<br />
$smtp->to($full);<br />
$smtp->data();<br />
$smtp->datasend("Subject: $subject");<br />
$smtp->datasend("To: " . $full . "\n");<br />
$smtp->datasend("From: " . $from_address . "\n");<br />
$smtp->datasend("\n");<br />
$smtp->datasend("@report\n");<br />
<br />
$smtp->dataend();<br />
$smtp->quit();<br />
};<br />
}</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=DueDateRemindersByEmail&diff=26465DueDateRemindersByEmail2017-01-08T20:40:31Z<p>Barton: /* New version ( 3.1 ) */</p>
<hr />
<div>The following script will send email notifications on Tickets that are over due.<br />
<br />
The following script will send email notifications on Tickets that are over due.<br />
<br />
Notes by [[User:Barton|Barton]]: I ran this page through a sed script that fixed the formatting of the nowiki formatted code blocks. You are encouraged to check the history of this page and make sure that I didn't mess anything up.<br />
<br />
== New version ( 3.1 ) ==<br />
<br />
====== New version ( 3.1 ) by Vaclav Vobornik added at 4.7.2008 ======<br />
<br />
i made a cleaned version be subsituting &lt; and &gt; to < and >. this apperently got lost while moving from wikia to here.<br />
<br />
also the preformatted text block syntax nowiki used below does not work here yet :(<br />
<br />
find it here: http://pastebin.com/gj5R7wm2<br />
<br />
####################### RT Email Notification Script ####################<br />
####<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Date: 05/06/05<br />
####<br />
#### Modified by: Tomas Borland Valenta<br />
#### Email: tomas at trustica dot cz<br />
#### Date: 2007/03/12<br />
####<br />
#### Modified by: Tim Schaller<br />
#### Email: tim-rt@torzo.com<br />
#### Date: 2008/06/17<br />
####<br />
#### Modified by: Vaclav Vobornik<br />
#### Email: vaclav dot vobornik at commerzbank dot com<br />
#### Date: 2008/07/04<br />
####<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
####<br />
#### Version: 3.1<br />
####<br />
#### Changes from 3 ( Vaclav Vobornik )<br />
#### - Added Cc and Bcc possibilities.<br />
####<br />
#### Changes from 2 ( Tim Schaller )<br />
#### - Added multiple command line options.<br />
#### - Adaptive subject line.<br />
#### - Sending Admin CC emails optional.<br />
####<br />
#### Changes from 1.2 ( Tomas Borland Valenta )<br />
#### - rewriten mail subsystem<br />
#### - code cleanup<br />
#### - adopted for RT 3.6.x<br />
#### - used some global RT config variables<br />
####<br />
#### ======================================================================<br />
####<br />
#### Command line options<br />
#### -d : turns dubugging on<br />
#### -A : Send to AdminCC ( made default not to )<br />
#### -a <n> : Send reminders to tickets due in <n> or less days.<br />
#### : Includes overdue tickets.<br />
#### -q <queue> : Only send reminder for tickets in <queue><br />
#### -o <owner> : Only send reminders for tickets owned by <owner><br />
#### -c <email> : Email in Cc<br />
#### -b <email> : Email in Bcc<br />
####<br />
#### ======================================================================<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### : Remind them about tickets due in less then 5 days.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -a 5 -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue.<br />
#### : Send copies to all AdminCC on the tickest.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A -q SysAdmin<br />
<br />
### External libraries ###<br />
use strict;<br />
use Getopt::Std;<br />
<br />
use lib ("/opt/rt3/lib"); # Change this to your RT lib path!<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
<br />
################## Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
# Set config variables<br />
my $debug=0;<br />
my $from_address = $RT::CorrespondAddress; #From: address used in reports<br />
my $rt_url = $RT::WebURL;<br />
my $sendmail = "$RT::SendmailPath $RT::SendmailArguments";<br />
<br />
################## Args ##################<br />
my $queue = '';<br />
my $owner = '';<br />
my $advDate = 0;<br />
my $secInDay = 60*60*24;<br />
my $sendToAdminCC = 0;<br />
my $cc = '';<br />
my $bcc = '';<br />
<br />
my %options=();<br />
Getopt::Std::getopts("Ada:q:o:c:b:",\%options);<br />
<br />
$queue = $options{q} if defined $options{q};<br />
$owner = $options{o} if defined $options{o};<br />
$advDate = ( $options{a} * $secInDay ) if defined $options{a};<br />
$debug = $options{d} if defined $options{d};<br />
$sendToAdminCC = $options{A} if defined $options{A};<br />
$cc = $options{c} if defined $options{c};<br />
$bcc = $options{b} if defined $options{b};<br />
<br />
<br />
################## Variables Init ##################<br />
my $User = new RT::User($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my $report; # Used for output<br />
my $subject; # Used as subject line<br />
<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix < (1 - $advDate ) or $date->Unix == -1 or $date->Unix == 0) { next; }<br />
<br />
# Compare owner and queue if given. Skip current ticket if invalid.<br />
if ($owner) { if ( lc($User->Name) ne lc($owner) ) { next; } }<br />
if ($queue) { if ( lc($Ticket->QueueObj->Name) ne lc($queue) ) { next; } }<br />
<br />
# Generate a report<br />
$report = "";<br />
$report .= "Ticket #: " . $Ticket->id . "\n";<br />
$report .= "Subject: " . $Ticket->Subject . "\n";<br />
$report .= "Queue: " . $Ticket->QueueObj->Name . " (". $Ticket->QueueObj->AdminCcAddresses .") \n";<br />
$report .= "Owner: " . $User->Name ."\n";<br />
$report .= "Due date: " . $date->ISO . "\n";<br />
$report .= "URL: " . $rt_url . "Ticket/Display.html?id=" . $Ticket->id . "\n";<br />
<br />
# Set the subject based on the due date.<br />
if( ($now->Unix - $date->Unix < 0 ) or $date->Unix == -1 ) {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is due on " . $date->ISO;<br />
} else {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is overdue";<br />
}<br />
<br />
# Get Queue Admin CC<br />
# Do we send to Admin CC as well as to owner?<br />
my @emails = ();<br />
if ( $sendToAdminCC ) {<br />
@emails = ($User->EmailAddress, split(/,/, $Ticket->AdminCcAddresses), split(/,/ , $Ticket->QueueObj->AdminCcAddresses));<br />
} else {<br />
@emails = ($User->EmailAddress);<br />
}<br />
<br />
# remove duplicates<br />
my %temp = (); @emails = grep ++$temp{$_} < 2, @emails;<br />
send_report(@emails);<br />
}<br />
<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
# This procedure will send a report by mail to the owner<br />
# parameter 1 - email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $from_address - address to send from<br />
# $cc - CarbonCoby email address<br />
# $bcc - BlindCarbonCopy email address<br />
sub send_report {<br />
my @tos = @_;<br />
my $addr;<br />
<br />
foreach $addr (@tos) {<br />
next if (length($addr) == 0);<br />
my $msg = "";<br />
$msg .= "From: $from_address\n";<br />
$msg .= "To: $addr\n";<br />
$msg .= "Cc: $cc\n" if $cc;<br />
$msg .= "Bcc: $bcc\n" if $bcc;<br />
$msg .= "Subject: $subject\n";<br />
$msg .= "\n";<br />
$msg .= $report;<br />
<br />
if ($debug) {<br />
print "====== Would call '$sendmail' with this input:\n";<br />
print "$msg\n\n";<br />
} else {<br />
open(SENDMAIL, "|$sendmail") || die "Error sending mail: $!";<br />
print SENDMAIL $msg;<br />
close(SENDMAIL);<br />
}<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
== Old version ( 3.0 ) ==<br />
<br />
====== Version ( 3.0 ) by Tim Schaller added at 17.6.2008 ======<br />
<br />
####################### RT Email Notification Script ####################<br />
####<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Date: 05/06/05<br />
####<br />
#### Modified by: Tomas Borland Valenta<br />
#### Email: tomas at trustica dot cz<br />
#### Date: 2007/03/12<br />
####<br />
#### Modified by: Tim Schaller<br />
#### Email: tim-rt@torzo.com<br />
#### Date: 2008/06/17<br />
####<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
####<br />
#### Version: 3<br />
####<br />
#### Changes from 2 ( Tim Schaller )<br />
#### - Added multiple command line options.<br />
#### - Adaptive subject line.<br />
#### - Sending Admin CC emails optional.<br />
####<br />
#### Changes from 1.2 ( Tomas Borland Valenta )<br />
#### - rewriten mail subsystem<br />
#### - code cleanup<br />
#### - adopted for RT 3.6.x<br />
#### - used some global RT config variables<br />
####<br />
#### ======================================================================<br />
####<br />
#### Command line options<br />
#### -d : turns dubugging on<br />
#### -A : Send to AdminCC ( made default not to )<br />
#### -a <n> : Send reminders to tickets due in <n> or less days.<br />
#### : Includes overdue tickets.<br />
#### -q <queue> : Only send reminder for tickets in <queue><br />
#### -o <owner> : Only send reminders for tickets owned by <owner><br />
####<br />
#### ======================================================================<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### : Remind them about tickets due in less then 5 days.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -a 5 -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue.<br />
#### : Send copies to all AdminCC on the tickest.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A -q SysAdmin<br />
<br />
### External libraries ###<br />
use strict;<br />
use Getopt::Std;<br />
<br />
use lib ("/usr/local/rt/lib"); # Change this to your RT lib path!<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
<br />
################## Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
# Set config variables<br />
my $debug=0;<br />
my $from_address = $RT::CorrespondAddress; #From: address used in reports<br />
my $rt_url = $RT::WebURL;<br />
my $sendmail = "$RT::SendmailPath $RT::SendmailArguments";<br />
<br />
################## Args ##################<br />
my $queue = '';<br />
my $owner = '';<br />
my $advDate = 0;<br />
my $secInDay = 60*60*24;<br />
my $sendToAdminCC = 0;<br />
<br />
my %options=();<br />
Getopt::Std::getopts("Ada:q:o:",\%options);<br />
<br />
$queue = $options{q} if defined $options{q};<br />
$owner = $options{o} if defined $options{o};<br />
$advDate = ( $options{a} * $secInDay ) if defined $options{a};<br />
$debug = $options{d} if defined $options{d};<br />
$sendToAdminCC = $options{A} if defined $options{A};<br />
<br />
################## Variables Init ##################<br />
my $User = new RT::User($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my $report; # Used for output<br />
my $subject; # Used as subject line<br />
<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix < (1 - $advDate ) or $date->Unix == -1) { next; }<br />
<br />
# Compare owner and queue if given. Skip current ticket if invalid.<br />
if ($owner) { if ( lc($User->Name) ne lc($owner) ) { next; } }<br />
if ($queue) { if ( lc($Ticket->QueueObj->Name) ne lc($queue) ) { next; } }<br />
<br />
# Generate a report<br />
$report = "";<br />
$report .= "Ticket #: " . $Ticket->id . "\n";<br />
$report .= "Subject: " . $Ticket->Subject . "\n";<br />
$report .= "Queue: " . $Ticket->QueueObj->Name . " (". $Ticket->QueueObj->AdminCcAddresses .") \n";<br />
$report .= "Owner: " . $User->Name ."\n";<br />
$report .= "Due date: " . $date->ISO . "\n";<br />
$report .= "URL: " . $rt_url . "Ticket/Display.html?id=" . $Ticket->id . "\n";<br />
<br />
# Set the subject based on the due date.<br />
if( ($now->Unix - $date->Unix < 0 ) or $date->Unix == -1 ) {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is due on " . $date->ISO;<br />
} else {<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is overdue";<br />
}<br />
<br />
# Do we send to Admin CC as well as to owner?<br />
my @emails = ();<br />
if ( $sendToAdminCC ) {<br />
@emails = ($User->EmailAddress, split(/,/, $Ticket->AdminCcAddresses), split(/,/ , $Ticket->QueueObj->AdminCcAddresses));<br />
} else {<br />
@emails = ($User->EmailAddress);<br />
}<br />
<br />
# remove duplicates<br />
my %temp = (); @emails = grep ++$temp{$_} < 2, @emails;<br />
send_report(@emails);<br />
}<br />
<br />
<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
# This procedure will send a report by mail to the owner<br />
# parameter 1 - email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $from_address - address to send from<br />
sub send_report {<br />
my @tos = @_;<br />
my $addr;<br />
<br />
foreach $addr (@tos) {<br />
next if (length($addr) == 0);<br />
my $msg = "";<br />
$msg .= "From: $from_address\n";<br />
$msg .= "To: $addr\n";<br />
$msg .= "Subject: $subject\n";<br />
$msg .= "\n";<br />
$msg .= $report;<br />
<br />
if ($debug) {<br />
print "====== Would call '$sendmail' with this input:\n";<br />
print "$msg\n\n";<br />
} else {<br />
open(SENDMAIL, "|$sendmail") || die "Error sending mail: $!";<br />
print SENDMAIL $msg;<br />
close(SENDMAIL);<br />
}<br />
}<br />
}<br />
<br />
<br />
<br />
== Old version ==<br />
<br />
====== Version by Tomas Borland Valenta added at 14.3.2007 ======<br />
<br />
####################### RT Email Notification Script ####################<br />
####<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Date: 05/06/05<br />
####<br />
#### Modified by: Tomas Borland Valenta<br />
#### Email: tomas at trustica dot cz<br />
#### Date: 2007/03/12<br />
####<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
####<br />
#### Version: 2<br />
#### Changes from 1.2<br />
#### - rewriten mail subsystem<br />
#### - code cleanup<br />
#### - adopted for RT 3.6.x<br />
#### - used some global RT config variables<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl<br />
<br />
### External libraries ###<br />
use strict;<br />
use lib ("/usr/share/request-tracker3.6/lib");<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
<br />
################## Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
# Set config variables<br />
my $debug=0;<br />
my $from_address = $RT::CorrespondAddress; #From: address used in reports<br />
my $rt_url = $RT::WebURL;<br />
my $sendmail = "$RT::SendmailPath $RT::SendmailArguments";<br />
<br />
################## Variables Init ##################<br />
my $User = new RT::User($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my $report; # Used for output<br />
my $subject; # Used as subject line<br />
<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix < 0 or $date->Unix == -1) { next; }<br />
# Generate a report<br />
$report = "";<br />
$report .= "Ticket #: " . $Ticket->id . "\n";<br />
$report .= "Subject: " . $Ticket->Subject . "\n";<br />
$report .= "Queue: " . $Ticket->QueueObj->Name . " (". $Ticket->QueueObj->AdminCcAddresses .") \n";<br />
$report .= "Owner: " . $User->Name ."\n";<br />
$report .= "Due date: " . $date->ISO . "\n";<br />
$report .= "URL: " . $rt_url . "Ticket/Display.html?id=" . $Ticket->id . "\n";<br />
$subject = "Ticket #". $Ticket->id . " with owner " . $User->Name ." is overdue";<br />
<br />
# Get Queue Admin CC<br />
my @emails = ($User->EmailAddress, split(/,/, $Ticket->AdminCcAddresses), split(/,/ , $Ticket->QueueObj->AdminCcAddresses));<br />
my %temp = (); @emails = grep ++$temp{$_} < 2, @emails; # remove duplicates<br />
send_report(@emails);<br />
}<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
# This procedure will send a report by mail to the owner<br />
# parameter 1 - email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $from_address - address to send from<br />
sub send_report {<br />
my @tos = @_;<br />
my $addr;<br />
<br />
foreach $addr (@tos) {<br />
next if (length($addr) == 0);<br />
my $msg = "";<br />
$msg .= "From: $from_address\n";<br />
$msg .= "To: $addr\n";<br />
$msg .= "Subject: $subject\n";<br />
$msg .= "\n";<br />
$msg .= $report;<br />
if ($debug) {<br />
print "====== Would call '$sendmail' with this input:\n";<br />
print "$msg\n\n";<br />
} else {<br />
open(SENDMAIL, "|$sendmail") || die "Error sending mail: $!";<br />
print SENDMAIL $msg;<br />
close(SENDMAIL);<br />
}<br />
}<br />
}<br />
<br />
<br />
== Old version ==<br />
<br />
====== Daniely Yoav, !QBall Technologies Ltd. yoavd![at]qballtech![dot]net ======<br />
<br />
You can cut/paste or download the script from [http://qballtech.net/rt_3_remind_email_due.pl.gz Notifications script]. Put the script in your daily crontab (/etc/cron.daily on Fedora Core)<br />
<br />
####################### RT Email Notification Script ####################<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
#### Version: 1.1<br />
#### Usage: Invoke via cron<br />
#### */5 * * * * /path/to/script/remind_email_due.pl<br />
#### Date: 05/06/05<br />
############################################################<br />
my $from_address = 'reports@demo.qballtech.net'; #From: address used in reports<br />
my $mail_host = 'localhost'; #Mail Server used for sending mail<br />
my $my_host = 'demo.qballtech.net'; # My FQDN<br />
my $rt_url = 'https://demo.qballtech.net/rt';<br />
<br />
# Days to send notifcations on<br />
# Enable Debug<br />
my $debug=0;<br />
# initalize<br />
use lib ("/usr/local/rt3/lib", "/usr/local/rt3/local/lib");<br />
############################################################<br />
################## DO NOT EDIT BELOW THIS LINE ##################<br />
################## External dependancies ##################<br />
use strict;<br />
use Carp;<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
use Mail::Internet;<br />
use Mail::Address;<br />
use Net::SMTP;<br />
use Encode;<br />
use MIME::Base64;<br />
use MIME::QuotedPrint;<br />
use MIME::Words qw(:all);<br />
<br />
################## RT Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
################## Variables Init ##################<br />
my $User = RT::User->new($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $pipe; # Used as PIPE to transfer data to smbclient<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now->SetToNow();<br />
my @report; # Used for output<br />
my $subject; # Used as subject line<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets->LimitStatus(VALUE => 'new');<br />
$tickets->LimitStatus(VALUE => 'open');<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets->Next) {<br />
# Construct POP-Up Message<br />
$User->Load($Ticket->Owner);<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date->Set(Format => "ISO",Value => $Ticket->Due);<br />
if ($now->Unix - $date->Unix > 0 and $date->Unix != -1) {<br />
# Generate a report<br />
@report = ();<br />
push (@report,"Ticket #" . $Ticket->id . " is over his due date. \n");<br />
push (@report,"Owner: " . $User->Name ."\n");<br />
push (@report,"Due date:" . $date->ISO . "\n");<br />
push (@report,"Subject: " . $Ticket->Subject . "\n");<br />
push (@report,"URL: " . $rt_url . "/Ticket/Display.html?id=" . $Ticket->id . "\n");<br />
push (@report,"\n\nTickets notifications script by Qball Solutions");<br />
push (@report,"\nplease report problems to solutions\@helpdesk.qballtech.net)");<br />
push(@report,"\nContact us! (info\@qballtech.net)\n");<br />
$subject = "Ticket #". $Ticket->id . " with Owner: " . $User->Name ." is over his due date\n";<br />
#print $line . "\n";<br />
#print $User->EmailAddress . "\n";<br />
# Send report by email<br />
# Get Queue Admin CC<br />
send_report($User->EmailAddress . "," . $Ticket->AdminCcAddresses . "," .$Ticket->QueueObj->AdminCcAddresses);<br />
print @report if $debug;<br />
}<br />
}<br />
# Close RT Handle<br />
$RT::Handle->Disconnect();<br />
exit 0;<br />
<br />
sub send_report {<br />
##########################<br />
# Send report procedure###<br />
##########################<br />
# This procedure will send a report by mail to the owner<br />
# Parameter 1) Email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $mail_host - mail relay host address<br />
# $from_address - address to send from<br />
my $smtp;<br />
my $addr;<br />
my $full;<br />
my $to_address = "$_[0]";<br />
my @addrs = Mail::Address->parse("$to_address");<br />
my $mime_type = 'TEXT';<br />
my $message = @report;<br />
foreach $addr (@addrs)<br />
{<br />
$full=$addr->format;<br />
$smtp = Net::SMTP->new($mail_host,Debug=> 0);<br />
die "Couldn't connect to server" unless $smtp;<br />
$smtp->mail( $from_address );<br />
$smtp->to($full);<br />
$smtp->data();<br />
$smtp->datasend("Subject: $subject");<br />
$smtp->datasend("To: " . $full . "\n");<br />
$smtp->datasend("From: " . $from_address . "\n");<br />
$smtp->datasend("\n");<br />
$smtp->datasend("@report\n");<br />
<br />
$smtp->dataend();<br />
$smtp->quit();<br />
};<br />
}<br />
<br />
== Old version ( 3.0 ) ==<br />
<br />
====== Version ( 3.0 ) by Tim Schaller added at 17.6.2008 ======<br />
<br />
<nowiki>#!/usr/bin/perl<br />
####################### RT Email Notification Script ####################<br />
####<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Date: 05/06/05<br />
####<br />
#### Modified by: Tomas Borland Valenta<br />
#### Email: tomas at trustica dot cz<br />
#### Date: 2007/03/12<br />
####<br />
#### Modified by: Tim Schaller<br />
#### Email: tim-rt@torzo.com<br />
#### Date: 2008/06/17<br />
####<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
####<br />
#### Version: 3<br />
####<br />
#### Changes from 2 ( Tim Schaller )<br />
#### - Added multiple command line options.<br />
#### - Adaptive subject line.<br />
#### - Sending Admin CC emails optional.<br />
####<br />
#### Changes from 1.2 ( Tomas Borland Valenta )<br />
#### - rewriten mail subsystem<br />
#### - code cleanup<br />
#### - adopted for RT 3.6.x<br />
#### - used some global RT config variables<br />
####<br />
#### ======================================================================<br />
####<br />
#### Command line options<br />
#### -d : turns dubugging on<br />
#### -A : Send to AdminCC ( made default not to )<br />
#### -a &lt;n&gt; : Send reminders to tickets due in &lt;n&gt; or less days.<br />
#### : Includes overdue tickets.<br />
#### -q &lt;queue&gt; : Only send reminder for tickets in &lt;queue&gt;<br />
#### -o &lt;owner&gt; : Only send reminders for tickets owned by &lt;owner&gt;<br />
####<br />
#### ======================================================================<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue<br />
#### : Remind them about tickets due in less then 5 days.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -a 5 -q SysAdmin<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### : and send notices to everyone in the SysAdmin Queue.<br />
#### : Send copies to all AdminCC on the tickest.<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl -A -q SysAdmin<br />
<br />
### External libraries ###<br />
use strict;<br />
use Getopt::Std;<br />
<br />
use lib ("/usr/local/rt/lib"); # Change this to your RT lib path!<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
<br />
################## Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
# Set config variables<br />
my $debug=0;<br />
my $from_address = $RT::CorrespondAddress; #From: address used in reports<br />
my $rt_url = $RT::WebURL;<br />
my $sendmail = "$RT::SendmailPath $RT::SendmailArguments";<br />
<br />
################## Args ##################<br />
my $queue = '';<br />
my $owner = '';<br />
my $advDate = 0;<br />
my $secInDay = 60*60*24;<br />
my $sendToAdminCC = 0;<br />
<br />
my %options=();<br />
Getopt::Std::getopts("Ada:q:o:",\%options);<br />
<br />
$queue = $options{q} if defined $options{q};<br />
$owner = $options{o} if defined $options{o};<br />
$advDate = ( $options{a} * $secInDay ) if defined $options{a};<br />
$debug = $options{d} if defined $options{d};<br />
$sendToAdminCC = $options{A} if defined $options{A};<br />
<br />
################## Variables Init ##################<br />
my $User = new RT::User($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now-&gt;SetToNow();<br />
my $report; # Used for output<br />
my $subject; # Used as subject line<br />
<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets-&gt;LimitStatus(VALUE =&gt; 'new');<br />
$tickets-&gt;LimitStatus(VALUE =&gt; 'open');<br />
<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets-&gt;Next) {<br />
# Construct POP-Up Message<br />
$User-&gt;Load($Ticket-&gt;Owner);<br />
<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date-&gt;Set(Format =&gt; "ISO",Value =&gt; $Ticket-&gt;Due);<br />
if ($now-&gt;Unix - $date-&gt;Unix &lt; (1 - $advDate ) or $date-&gt;Unix == -1) { next; }<br />
<br />
# Compare owner and queue if given. Skip current ticket if invalid.<br />
if ($owner) { if ( lc($User-&gt;Name) ne lc($owner) ) { next; } }<br />
if ($queue) { if ( lc($Ticket-&gt;QueueObj-&gt;Name) ne lc($queue) ) { next; } }<br />
<br />
# Generate a report<br />
$report = "";<br />
$report .= "Ticket #: " . $Ticket-&gt;id . "\n";<br />
$report .= "Subject: " . $Ticket-&gt;Subject . "\n";<br />
$report .= "Queue: " . $Ticket-&gt;QueueObj-&gt;Name . " (". $Ticket-&gt;QueueObj-&gt;AdminCcAddresses .") \n";<br />
$report .= "Owner: " . $User-&gt;Name ."\n";<br />
$report .= "Due date: " . $date-&gt;ISO . "\n";<br />
$report .= "URL: " . $rt_url . "Ticket/Display.html?id=" . $Ticket-&gt;id . "\n";<br />
<br />
# Set the subject based on the due date.<br />
if( ($now-&gt;Unix - $date-&gt;Unix &lt; 0 ) or $date-&gt;Unix == -1 ) {<br />
$subject = "Ticket #". $Ticket-&gt;id . " with owner " . $User-&gt;Name ." is due on " . $date-&gt;ISO;<br />
} else {<br />
$subject = "Ticket #". $Ticket-&gt;id . " with owner " . $User-&gt;Name ." is overdue";<br />
}<br />
</nowiki><br />
<br />
<nowiki> # Get Queue Admin CC<br />
# Do we send to Admin CC as well as to owner?<br />
my @emails = ();<br />
if ( $sendToAdminCC ) {<br />
@emails = ($User-&gt;EmailAddress, split(/,/, $Ticket-&gt;AdminCcAddresses), split(/,/ , $Ticket-&gt;QueueObj-&gt;AdminCcAddresses));<br />
} else {<br />
@emails = ($User-&gt;EmailAddress);<br />
}<br />
<br />
# remove duplicates<br />
my %temp = (); @emails = grep ++$temp{$_} &lt; 2, @emails;<br />
send_report(@emails);<br />
}<br />
<br />
<br />
# Close RT Handle<br />
$RT::Handle-&gt;Disconnect();<br />
exit 0;<br />
<br />
# This procedure will send a report by mail to the owner<br />
# parameter 1 - email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $from_address - address to send from<br />
sub send_report {<br />
my @tos = @_;<br />
my $addr;<br />
<br />
foreach $addr (@tos) {<br />
next if (length($addr) == 0);<br />
my $msg = "";<br />
$msg .= "From: $from_address\n";<br />
$msg .= "To: $addr\n";<br />
$msg .= "Subject: $subject\n";<br />
$msg .= "\n";<br />
$msg .= $report;<br />
<br />
if ($debug) {<br />
print "====== Would call '$sendmail' with this input:\n";<br />
print "$msg\n\n";<br />
} else {<br />
open(SENDMAIL, "|$sendmail") || die "Error sending mail: $!";<br />
print SENDMAIL $msg;<br />
close(SENDMAIL);<br />
}<br />
}<br />
}<br />
<br />
<br />
</nowiki><br />
<br />
== Old version ==<br />
<br />
====== Version by Tomas Borland Valenta added at 14.3.2007 ======<br />
<br />
<nowiki>#!/usr/bin/perl -w<br />
####################### RT Email Notification Script ####################<br />
####<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Date: 05/06/05<br />
####<br />
#### Modified by: Tomas Borland Valenta<br />
#### Email: tomas at trustica dot cz<br />
#### Date: 2007/03/12<br />
####<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
####<br />
#### Version: 2<br />
#### Changes from 1.2<br />
#### - rewriten mail subsystem<br />
#### - code cleanup<br />
#### - adopted for RT 3.6.x<br />
#### - used some global RT config variables<br />
####<br />
#### Usage: Invoke via cron every working day at 8 morning<br />
#### 0 8 * * 1-5 /path/to/script/remind_email_due.pl<br />
<br />
### External libraries ###<br />
use strict;<br />
use lib ("/usr/share/request-tracker3.6/lib");<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
<br />
################## Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
# Set config variables<br />
my $debug=0;<br />
my $from_address = $RT::CorrespondAddress; #From: address used in reports<br />
my $rt_url = $RT::WebURL;<br />
my $sendmail = "$RT::SendmailPath $RT::SendmailArguments";<br />
<br />
################## Variables Init ##################<br />
my $User = new RT::User($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now-&gt;SetToNow();<br />
my $report; # Used for output<br />
my $subject; # Used as subject line<br />
<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets-&gt;LimitStatus(VALUE =&gt; 'new');<br />
$tickets-&gt;LimitStatus(VALUE =&gt; 'open');<br />
<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets-&gt;Next) {<br />
# Construct POP-Up Message<br />
$User-&gt;Load($Ticket-&gt;Owner);<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date-&gt;Set(Format =&gt; "ISO",Value =&gt; $Ticket-&gt;Due);<br />
if ($now-&gt;Unix - $date-&gt;Unix &lt; 0 or $date-&gt;Unix == -1) { next; }<br />
# Generate a report<br />
$report = "";<br />
$report .= "Ticket #: " . $Ticket-&gt;id . "\n";<br />
$report .= "Subject: " . $Ticket-&gt;Subject . "\n";<br />
$report .= "Queue: " . $Ticket-&gt;QueueObj-&gt;Name . " (". $Ticket-&gt;QueueObj-&gt;AdminCcAddresses .") \n";<br />
$report .= "Owner: " . $User-&gt;Name ."\n";<br />
$report .= "Due date: " . $date-&gt;ISO . "\n";<br />
$report .= "URL: " . $rt_url . "Ticket/Display.html?id=" . $Ticket-&gt;id . "\n";<br />
$subject = "Ticket #". $Ticket-&gt;id . " with owner " . $User-&gt;Name ." is overdue";<br />
<br />
# Get Queue Admin CC<br />
my @emails = ($User-&gt;EmailAddress, split(/,/, $Ticket-&gt;AdminCcAddresses), split(/,/ , $Ticket-&gt;QueueObj-&gt;AdminCcAddresses));<br />
my %temp = (); @emails = grep ++$temp{$_} &lt; 2, @emails; # remove duplicates<br />
send_report(@emails);<br />
}<br />
# Close RT Handle<br />
$RT::Handle-&gt;Disconnect();<br />
exit 0;<br />
<br />
# This procedure will send a report by mail to the owner<br />
# parameter 1 - email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $from_address - address to send from<br />
sub send_report {<br />
my @tos = @_;<br />
my $addr;<br />
<br />
foreach $addr (@tos) {<br />
next if (length($addr) == 0);<br />
my $msg = "";<br />
$msg .= "From: $from_address\n";<br />
$msg .= "To: $addr\n";<br />
$msg .= "Subject: $subject\n";<br />
$msg .= "\n";<br />
$msg .= $report;<br />
<br />
if ($debug) {<br />
print "====== Would call '$sendmail' with this input:\n";<br />
print "$msg\n\n";<br />
} else {<br />
open(SENDMAIL, "|$sendmail") || die "Error sending mail: $!";<br />
print SENDMAIL $msg;<br />
close(SENDMAIL);<br />
}<br />
}<br />
}<br />
<br />
</nowiki><br />
<br />
== Old version ==<br />
<br />
====== Daniely Yoav, !QBall Technologies Ltd. yoavd![at]qballtech![dot]net ======<br />
<br />
You can cut/paste or download the script from [http://qballtech.net/rt_3_remind_email_due.pl.gz Notifications script]. Put the script in your daily crontab (/etc/cron.daily on Fedora Core)<br />
<br />
<nowiki>#!/usr/bin/perl -w<br />
####################### RT Email Notification Script ####################<br />
#### Author: Daniely Yoav / Qball Technologies Ltd.<br />
#### Email: yoavd@qballtech.net<br />
#### Purpose: Send Email Notification on all open/new tickets in RT that have their due date expired<br />
#### Version: 1.1<br />
#### Usage: Invoke via cron<br />
#### */5 * * * * /path/to/script/remind_email_due.pl<br />
#### Date: 05/06/05<br />
############################################################<br />
my $from_address = 'reports@demo.qballtech.net'; #From: address used in reports<br />
my $mail_host = 'localhost'; #Mail Server used for sending mail<br />
my $my_host = 'demo.qballtech.net'; # My FQDN<br />
my $rt_url = 'https://demo.qballtech.net/rt';<br />
<br />
# Days to send notifcations on<br />
# Enable Debug<br />
my $debug=0;<br />
# initalize<br />
use lib ("/usr/local/rt3/lib", "/usr/local/rt3/local/lib");<br />
############################################################<br />
################## DO NOT EDIT BELOW THIS LINE ##################<br />
################## External dependancies ##################<br />
use strict;<br />
use Carp;<br />
package RT;<br />
use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);<br />
use RT::Date;<br />
use RT::Queue;<br />
use RT::Queues;<br />
use RT::Tickets;<br />
use Mail::Internet;<br />
use Mail::Address;<br />
use Net::SMTP;<br />
use Encode;<br />
use MIME::Base64;<br />
use MIME::QuotedPrint;<br />
use MIME::Words qw(:all);<br />
<br />
################## RT Init ##################<br />
# Clean our environment<br />
CleanEnv();<br />
# Load the RT configuration<br />
RT::LoadConfig();<br />
RT::Init();<br />
################## Variables Init ##################<br />
my $User = RT::User-&gt;new($RT::SystemUser); # Define an RT User variable<br />
my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)<br />
my $pipe; # Used as PIPE to transfer data to smbclient<br />
my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results<br />
my $now = new RT::Date($RT::SystemUser); # get current time<br />
$now-&gt;SetToNow();<br />
my @report; # Used for output<br />
my $subject; # Used as subject line<br />
################## Main Program ##################<br />
# Limit the ticket search to new and open only.<br />
$tickets-&gt;LimitStatus(VALUE =&gt; 'new');<br />
$tickets-&gt;LimitStatus(VALUE =&gt; 'open');<br />
# Loop through new/open tickets<br />
while (my $Ticket = $tickets-&gt;Next) {<br />
# Construct POP-Up Message<br />
$User-&gt;Load($Ticket-&gt;Owner);<br />
# Compare Dates to check whether the ticket's due date is in the past + Due date exists<br />
$date-&gt;Set(Format =&gt; "ISO",Value =&gt; $Ticket-&gt;Due);<br />
if ($now-&gt;Unix - $date-&gt;Unix &gt; 0 and $date-&gt;Unix != -1) {<br />
# Generate a report<br />
@report = ();<br />
push (@report,"Ticket #" . $Ticket-&gt;id . " is over his due date. \n");<br />
push (@report,"Owner: " . $User-&gt;Name ."\n");<br />
push (@report,"Due date:" . $date-&gt;ISO . "\n");<br />
push (@report,"Subject: " . $Ticket-&gt;Subject . "\n");<br />
push (@report,"URL: " . $rt_url . "/Ticket/Display.html?id=" . $Ticket-&gt;id . "\n");<br />
push (@report,"\n\nTickets notifications script by Qball Solutions");<br />
push (@report,"\nplease report problems to solutions\@helpdesk.qballtech.net)");<br />
push(@report,"\nContact us! (info\@qballtech.net)\n");<br />
$subject = "Ticket #". $Ticket-&gt;id . " with Owner: " . $User-&gt;Name ." is over his due date\n";<br />
#print $line . "\n";<br />
#print $User-&gt;EmailAddress . "\n";<br />
# Send report by email<br />
# Get Queue Admin CC<br />
send_report($User-&gt;EmailAddress . "," . $Ticket-&gt;AdminCcAddresses . "," .$Ticket-&gt;QueueObj-&gt;AdminCcAddresses);<br />
print @report if $debug;<br />
}<br />
}<br />
# Close RT Handle<br />
$RT::Handle-&gt;Disconnect();<br />
exit 0;<br />
<br />
sub send_report {<br />
##########################<br />
# Send report procedure###<br />
##########################<br />
# This procedure will send a report by mail to the owner<br />
# Parameter 1) Email addresses to send to<br />
# Global variables refered to:<br />
# $subject - Subject line<br />
# @report - Message content<br />
# $mail_host - mail relay host address<br />
# $from_address - address to send from<br />
my $smtp;<br />
my $addr;<br />
my $full;<br />
my $to_address = "$_[0]";<br />
my @addrs = Mail::Address-&gt;parse("$to_address");<br />
my $mime_type = 'TEXT';<br />
my $message = @report;<br />
foreach $addr (@addrs)<br />
{<br />
$full=$addr-&gt;format;<br />
$smtp = Net::SMTP-&gt;new($mail_host,Debug=&gt; 0);<br />
die "Couldn't connect to server" unless $smtp;<br />
$smtp-&gt;mail( $from_address );<br />
$smtp-&gt;to($full);<br />
$smtp-&gt;data();<br />
$smtp-&gt;datasend("Subject: $subject");<br />
$smtp-&gt;datasend("To: " . $full . "\n");<br />
$smtp-&gt;datasend("From: " . $from_address . "\n");<br />
$smtp-&gt;datasend("\n");<br />
$smtp-&gt;datasend("@report\n");<br />
<br />
$smtp-&gt;dataend();<br />
$smtp-&gt;quit();<br />
};<br />
}<br />
</nowiki></div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=UntouchedInBusinessHours&diff=26464UntouchedInBusinessHours2017-01-08T19:19:16Z<p>Barton: /* Crontab Entries -- reformat */</p>
<hr />
<div>= UntouchedInBusinessHours =<br />
<br />
Based on the Modul/Condition [[UntouchedInHours]] and the Ideas from [[TimedNotifications]] we created a new Condition called [[UntouchedInBusinessHours]].<br />
<br />
Compared to [[UntouchedInHours]] we calculate within this module based on the Create Time of the Ticket and not on [[LastUpdated]] and also only within a definable Business Hours Range.<br />
<br />
== Problem Scenario ==<br />
<br />
We needed in some Change Request Queues some kind of escalation mixed with notifications based on given business hours model. This escalation should be done in two steps, first escalation should inform head of the queue and raise the ticket priority and second should inform head of IT and raise the priority again.<br />
<br />
== Solution ==<br />
<br />
As solution for this setup we found a mixture of rtcrontool / cron, [[UntouchedInHours]] and [[TimedNotifications]].<br />
<br />
=== Crontab Entries ===<br />
<br />
*/15 7-15 * * * /opt/rt3/bin/rt-crontool<br />
--search RT::Search::FromSQL<br />
--search-arg "Queue = 'ChangeManagement' AND Status = 'new' AND Owner = 'Nobody' AND CF.Escalation = 'InTime'"<br />
--condition RT::Condition::UntouchedInBusinessHours<br />
--condition-arg 8:7:15:0<br />
--action RT::Action::RecordComment<br />
--template 'esc 1 - 8Std FirstContact'<br />
<br />
=== Queue Preparation ===<br />
<br />
To make sure to escalate in the correct order, we added to each change queue a [[CustomField]] and a Custom Scrip<br />
<br />
==== CustomFields ====<br />
<br />
For each Change Queue we added a [[CustomField]] Escalation which will be filled at ticket creation with the Value "[[InTime]]" and updated after first escalation with the Value "[[FirstEscalation]]" and after second escalation with the value "[[SecondEscalation]]" This values are used inside the search as additional Search Argument.<br />
<br />
==== Custom Scrip ====<br />
<br />
We added to all change queues a simple scrip which set the CF Escalation at ticket create time to "[[InTime]]"<br />
<br />
Scrip: 001_[[OnCreateSetEscalationCF]]<br />
<br />
Condition: [[OnCreate]] Action: [[UserDefined]] Template: Blank<br />
<br />
Custom action preparation code:<br />
<br />
return 1;<br />
<br />
Custom action cleanup code:<br />
<br />
$self-&gt;[[TicketObj]]-&gt;[[AddCustomFieldValue]](Field =&gt; 'Escalation', Value =&gt; '[[InTime]]', [[RecordTransaction]] =&gt; 0); return 1;<br />
<br />
==== Templates ====<br />
<br />
Based on the ideas from we create some templates for the escalation, which will sent out a mail and raise the priority by 10 and update the [[CustomField]] "Escalation"<br />
<br />
Template: esc 1 - 8Std [[FirstContact]]<br />
<br />
Subject: Escalation 1 for Ticket #: {$Ticket-&gt;id} - {$Ticket-&gt;Subject()}!<br />
<br />
<nowiki>RT-Send-Cc: head1@company.com<br />
<br />
Hello,<br />
<br />
this is an automated Escalation Mail from the Request Tracker.<br />
<br />
!!!! FIRST ESCALATION !!!!<br />
<br />
The following Change Request is older than 8 hours without being attended to.<br />
<br />
Ticket Id: {$Ticket-&gt;id}<br />
Queue name: {$Ticket-&gt;QueueObj-&gt;Name}<br />
Escalation: {$Ticket-&gt;AddCustomFieldValue(Field =&gt;'Escalation', Value =&gt; 'FirstEscalation',RecordTransaction =&gt; 0)}<br />
Priority: {$Ticket-&gt;SetPriority($Ticket-&gt;Priority + 10)}<br />
Subject: {$Ticket-&gt;Subject()}<br />
Requestor: {$Ticket-&gt;RequestorAddresses}<br />
Ticket URL: {$RT::WebURL}Ticket/Display.html?id={$Ticket-&gt;id}<br />
<br />
Please take care of the Change Request immediately.<br />
<br />
Thank you<br />
</nowiki><br />
<br />
=== RT::Condition::UntouchedInBusinessHours ===<br />
<br />
After all the preparation, we implemented our new Condition to RT under RT_HOME/local/lib/RT/Condition called [[UntouchedInBusinessHours]].pm<br />
<br />
You can download the file here: [http://www.systemaniacs.de/wordpress/wp-content/uploads/2008/11/untouchedinbusinesshours.pm http://www.brumm.me/rt/UntouchInBusinessHours.pm]<br />
<br />
----<br />
<br />
package RT::Condition::[[UntouchedInBusinessHours]];<br />
<br />
<nowiki>require RT::Condition::Generic;<br />
<br />
use strict;<br />
use Time::Local;<br />
use vars qw/@ISA/;<br />
<br />
@ISA = qw(RT::Condition::Generic);<br />
<br />
=head1 NAME<br />
<br />
L&lt;RT::Condition::UntouchedInBusinessHours&gt; - Check for untouched Tickets within business hours<br />
<br />
=head1 SYNOPSIS<br />
<br />
=head2 CLI<br />
<br />
rt-crontool<br />
--search RT::Search::ModuleName<br />
--search-arg "The Search Argument"<br />
--condition RT::Condition::UntouchedInBusinessHours<br />
--condition-arg "The Condition Argument"<br />
--action RT::Action:ActionModule<br />
--template 'Template Name or ID'<br />
<br />
=head1 DESCRIPTION<br />
<br />
L&lt;RT::Condition::UntouchedInBusinessHours&gt; is a RT Condition which will check<br />
for untouched Tickets within business hours.<br />
Untouched means in this case really untouched from time of ticket creation.<br />
<br />
=head1 CONFIGURATION<br />
<br />
=head2 Condition Argument<br />
<br />
The L&lt;RT::Condition::UntouchedInBusinessHours&gt; need exactly 4 arguments to work.<br />
Each part of the argument is separated by colons.<br />
<br />
--condition RT::Condition::UntouchedInBusinessHours<br />
--condition-arg 1:7:15:0<br />
<br />
1 is the time in hours for escalation<br />
7 is the start hour of the working day<br />
15 is the end of of the working day<br />
0 is a 5 day week from monday to friday<br />
1 is a 7 day week from monday to sunday<br />
<br />
<br />
=head2 Example cron call<br />
<br />
rt-crontool<br />
--search RT::Search::FromSQL<br />
--search-arg "Queue = 'General' AND ( Status = 'new' ) AND Owner = 'Nobody'"<br />
--condition RT::Condition::UntouchedInBusinessHours<br />
--condition-arg 1:7:15:0<br />
--action RT::Action::RecordComment<br />
--template 'Unowned tickets'<br />
<br />
=head1 Limitations<br />
<br />
At this moment only week/weekends from mo-fr/sa-su are supported. If you have different scenario<br />
(like arabic countries) you have to change inside the source code ($wd =~ m/(Sun|Sat)/io)<br />
<br />
Also no public holidays are excluded.<br />
<br />
=head1 NOTES<br />
<br />
=head2 Reporting<br />
<br />
Send reports to L&lt;/AUTHOR&gt; or to the RT mailing lists.<br />
<br />
=head2 AUTHOR<br />
<br />
Torsten Brumm &lt;torsten.brumm@googlemail.com&gt;<br />
<br />
=head2 COPYRIGHT<br />
<br />
This program is free software; you can redistribute<br />
it and/or modify it under the same terms as Perl itself.<br />
<br />
The full text of the license can be found in the<br />
Perl distribution.<br />
<br />
=cut<br />
<br />
my ($est, $tc, $bsh, $beh, $te, $we);<br />
my ($sec,$min,$hour,$mday,$mon,$year,$wd);<br />
my $ActualDate;<br />
my $ticketObj;<br />
my $tickid;<br />
my $EscalationDate;<br />
<br />
sub IsApplicable {<br />
my $self = shift;<br />
$ticketObj = $self-&gt;TicketObj;<br />
$tickid = $ticketObj-&gt;Id;<br />
$tc = $ticketObj-&gt;CreatedObj-&gt;Unix;<br />
($est, $bsh, $beh, $we) = split(/:/, $self-&gt;Argument);<br />
$ActualDate = local_actual_date_sec(RT::Date-&gt;new($RT::SystemUser));<br />
$EscalationDate = escalate(normalize($tc, $bsh, $beh, $we), $bsh, $beh, $est, $we);<br />
if ( $EscalationDate &lt;= $ActualDate ) {<br />
return 1;<br />
}<br />
return undef;<br />
}<br />
<br />
sub local_actual_date_sec {<br />
my $self = shift;<br />
$self-&gt;SetToNow;<br />
my $Ausgabe_local_actual_date_sec = $self-&gt;Unix;<br />
return ($self-&gt;Unix);<br />
}<br />
<br />
sub escalate {<br />
my ($tc, $bs, $be, $et, $we) = @_;<br />
my ($rs, $es);<br />
my $bar = 60*60;<br />
$rs = $es = $et*$bar;<br />
my $elapsed = 0;<br />
my ($sec,$min,$hour,$mday,$mon,$year,$wd) = fromepoch($tc);<br />
my $beepo = timegm(0,0,$be,$mday,$mon,$year);<br />
my ($besec,$bemin,$behour,$bemday,$bemon,$beyear,$bewd) = fromepoch($beepo);<br />
my $foo = $beepo-$tc;<br />
if ($es &lt; $foo) { # escalate on the same day within BH<br />
return $tc+$es;<br />
}<br />
<br />
if ($hour &lt; $behour) {<br />
$elapsed += $foo;<br />
$rs -= $foo;<br />
($sec,$min,$hour,$mday,$mon,$year,$wd) = fromepoch($tc+86400);<br />
$tc = timegm(0,0,$bs,$mday,$mon,$year);<br />
$tc = normalize($tc, $bs, $be, $we);<br />
($sec,$min,$hour,$mday,$mon,$year,$wd) = fromepoch($tc);<br />
}<br />
<br />
while(int($rs / ($bar*($be -$bs)))) {<br />
$elapsed += ($bar * ($be -$bs));<br />
$rs -= ($bar * ($be - $bs));<br />
($sec,$min,$hour,$mday,$mon,$year,$wd) = fromepoch($tc+86400);<br />
$tc = timegm(0,0,$bs,$mday,$mon,$year);<br />
$tc = normalize($tc, $bs, $be, $we);<br />
($sec,$min,$hour,$mday,$mon,$year,$wd) = fromepoch($tc);<br />
}<br />
<br />
$tc = normalize($tc+$rs, $bs, $be);<br />
return $tc;<br />
}<br />
<br />
sub normalize {<br />
my ($time, $bs, $be, $we) = @_;<br />
my ($sec,$min,$hour,$mday,$mon,$year,$wd) = fromepoch($time);<br />
my $bens = timegm(0,0,$bs,$mday,$mon,$year);<br />
my $bend = timegm(0,0,$be,$mday,$mon,$year);<br />
if ($time &gt;= $bend) {<br />
($sec,$min,$hour,$mday,$mon,$year,$wd) = fromepoch($time+86400);<br />
$time = $bens = timegm(0,0,$bs,$mday,$mon,$year);<br />
$bend = timegm(0,0,$be,$mday,$mon,$year);<br />
}<br />
if ($time &lt; $bens) {<br />
$time = timegm(0,0,$bs,$mday,$mon,$year);<br />
}<br />
if (! $we) {<br />
while ($wd =~ m/(Sun|Sat)/io) {<br />
($sec,$min,$hour,$mday,$mon,$year,$wd) = fromepoch($time + 86400);<br />
$time = timegm(0,0,$bs,$mday,$mon,$year);<br />
}<br />
}<br />
return $time;<br />
}<br />
<br />
sub fromepoch {<br />
my ($t) = @_;<br />
my @time = gmtime($t);<br />
my $ss = ($time[0]&lt;10) ? "0".$time[0] : $time[0];<br />
my $mm = ($time[1]&lt;10) ? "0".$time[1] : $time[1];<br />
my $hh = ($time[2]&lt;10) ? "0".$time[2] : $time[2];<br />
my $day = $time[3];<br />
my $month = ($time[4] &lt; 10) ? "0".($time[4]) : $time[4];<br />
my $wday = ("Sun","Mon","Tue","Wed","Thu","Fri","Sat")[$time[6]];<br />
my $year = $time[5] + 1900;<br />
my $offset = timelocal(localtime) - timelocal(gmtime);<br />
my $sign ="+";<br />
if ($offset &lt; 0) {<br />
$sign ="-";<br />
$offset *= -1;<br />
}<br />
my $offseth = int($offset/3600);<br />
my $offsetm = int(($offset - $offseth*3600)/60);<br />
my $tz = sprintf ("%s%0.2d%0.2d", $sign, $offseth, $offsetm);<br />
return ($ss, $mm, $hh, $day, $month, $year, $wday);<br />
}<br />
<br />
eval "require RT::Condition::UntouchedInBusinessHours_Vendor";<br />
die $@ if ($@ &amp;&amp; $@ !~ qr{^Can't locate RT/Condition/UntouchedInBusinessHours_Vendor.pm});<br />
eval "require RT::Condition::UntouchedInBusinessHours_Local";<br />
die $@ if ($@ &amp;&amp; $@ !~ qr{^Can't locate RT/Condition/UntouchedInBusinessHours_Local.pm});<br />
<br />
1;<br />
<br />
</nowiki><br />
<br />
----</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=UntouchedInHours&diff=26463UntouchedInHours2017-01-08T19:17:58Z<p>Barton: /* A condition for rt-crontool -- code cleanup */</p>
<hr />
<div>= UntouchedInHours =<br />
<br />
=== A condition for rt-crontool ===<br />
<br />
RT's Crontool (<code>bin/rt-crontool</code>) offers several recipes for cron jobs. Here's one:<br />
<br />
bin/rt-crontool \<br />
--search RT::Search::ActiveTicketsInQueue --search-arg general \<br />
--condition RT::Condition::UntouchedInHours --condition-arg 4 \<br />
--action RT::Action::SetPriority --action-arg 99 \<br />
--verbose<br />
<br />
<br />
Some of the examples don't work out-of-the-box because they're just examples. Creating your own conditions is not hard, but to save you the couple of seconds, and if you would like to use the [[UntouchedInHours]] condition, save the following code to [=local/lib/RT/Condition/[[UntouchedInHours]].pm]<br />
<br />
package RT::Condition::UntouchedInHours;<br />
require RT::Condition::Generic;<br />
<br />
use strict;<br />
use vars qw/@ISA/;<br />
<br />
# We inherit from RT::Condition::Generic so we don't have to write (and maintain)<br />
# all the other stuff that goes into a condition<br />
@ISA = qw(RT::Condition::Generic);<br />
<br />
<br />
=head2 IsApplicable<br />
<br />
If the ticket's LastUpdated is more than n hours ago<br />
<br />
=cut<br />
<br />
# We just need to include this one function. I could have put everything in here but in<br />
# order to demonstrate the use of external functions, I've created the local_ageinhours<br />
# function. The function subtracts the LastUpdated time (as an Epoch timestamp) from the<br />
# current time stamp, then turns these seconds into hours.<br />
# The main function then just checks if this number is greater or equal to the argument<br />
# the crontool passed in.<br />
#<br />
# Note that the main function MUST be called 'IsApplicable'. For complex conditions it<br />
# may be best to create other functions as I've done here - so long as they're called<br />
# from IsApplicable.<br />
# I'd suggest naming your own functions with a 'local_' prefix so as to be certain not<br />
# to overwrite any current or future core function.<br />
<br />
sub IsApplicable {<br />
my $self = shift;<br />
if ( local_ageInHours($self->TicketObj) >= $self->Argument ) {<br />
# Returning true (1) indicates that this condition is true<br />
return 1;<br />
} else {<br />
# Returning undef indicates that this condition is false<br />
return undef;<br />
}<br />
}<br />
<br />
sub local_ageInHours {<br />
my $ticketObj = shift;<br />
return (time - $ticketObj->LastUpdatedObj->Unix) / (60*60);<br />
}<br />
<br />
<br />
# The following could be omitted. They're there to allow overrides from Vendor and Local<br />
# but as this isn't a core module, they're just there for completeness :)<br />
<br />
eval "require RT::Condition::UntouchedInHours_Vendor";<br />
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Condition/UntouchedInHours_Vendor.pm});<br />
eval "require RT::Condition::UntouchedInHours_Local";<br />
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Condition/UntouchedInHours_Local.pm});<br />
<br />
# If you weren't already aware, all perl modules need to evaluate to true. So we<br />
# force it to evaluate to true by finishing with a '1'.<br />
1;<br />
<br />
==== Alternative Version ====<br />
<br />
Could not get the above example to work successfully so I have created an alternative version (as simple as I could make it):<br />
<br />
package RT::Condition::UntouchedInHours;<br />
require RT::Condition::Generic;<br />
<br />
use RT::Date;<br />
<br />
<br />
@ISA = qw(RT::Condition::Generic);<br />
<br />
<br />
use strict;<br />
use vars qw/@ISA/;<br />
<br />
sub IsApplicable {<br />
my $self = shift;<br />
if ((time()-$self->TicketObj->LastUpdatedObj->Unix)/3600 >= $self->Argument) {<br />
return 1<br />
}<br />
else {<br />
return 0;<br />
}<br />
}<br />
<br />
# The following could be omitted. They're there to allow overrides from Vendor and Local<br />
# but as this isn't a core module, they're just there for completeness :)<br />
eval "require RT::Condition::UntouchedInHours_Vendor";<br />
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Condition/UntouchedInHours_Vendor.pm});<br />
eval "require RT::Condition::UntouchedInHours_Local";<br />
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Condition/UntouchedInHours_Local.pm});<br />
<br />
1;<br />
<br />
Just a footnote on that, I have fixed 2 mistakes spotted in the origional example. It '''may''' work now. I am using the Alternative version simply because I prefer its brevity.<br />
<br />
==== Alternative Version: UntouchedInBusinessHours ====<br />
<br />
Based on this module, i created a additional Modul [[[UntouchedInBusinessHours]].pm] based on Business Hour calculation.<br />
<br />
==== Yet Another Alternative Version ====<br />
<br />
At our site, we have a number of automatic operations that update a ticket's *LastUpdated* value, which means that it's not so useful for determining when the ticket owner last touched the ticket. This version works for us:<br />
<br />
package RT::Condition::UntouchedInHours;<br />
require RT::Condition::Generic;<br />
<br />
# RT::Date::Set kept misbehaving when fed an ISO-formatted string<br />
require DateTime::Format::MySQL;<br />
<br />
@ISA = qw(RT::Condition::Generic);<br />
<br />
use strict;<br />
use vars qw/@ISA/;<br />
<br />
# default age threshold<br />
use constant HOURS => 4;<br />
<br />
sub IsApplicable {<br />
my $self = shift;<br />
my $hours = $self->Argument || HOURS;<br />
<br />
# validate input<br />
unless ( $hours =~ /^\d+$/ ) {<br />
$hours = HOURS;<br />
}<br />
<br />
my $threshold = $hours * 60 * 60;<br />
my $now = time();<br />
my $last = local_lastCorrespondence( $self->TicketObj );<br />
<br />
if ( ( $last > 0 ) && ( $last + $threshold < $now ) ) {<br />
# this ticket has not been touched recently enough<br />
return $last;<br />
}<br />
else {<br />
return 0;<br />
}<br />
}<br />
<br />
sub local_lastCorrespondence {<br />
my $ticketObj = shift;<br />
<br />
# list the transactions<br />
my $transactions = $ticketObj->Transactions;<br />
<br />
# only the Correspondence, please<br />
$transactions->Limit( FIELD => 'Type', VALUE => 'Correspond' );<br />
<br />
# sort in descending order, by creation time then id<br />
$transactions->OrderByCols (<br />
{ FIELD => 'Created', ORDER => 'DESC' },<br />
{ FIELD => 'id', ORDER => 'DESC' },<br />
);<br />
<br />
# get the latest reply<br />
my $timestamp;<br />
my $transactionObj = $transactions->First;<br />
<br />
if ( defined( $transactionObj) && $transactionObj->id ) {<br />
# if the last Correspondence was from a requestor, check the time<br />
if ( $transactionObj->IsInbound ) {<br />
<br />
my $last = DateTime::Format::MySQL->parse_datetime( $transactionObj->Created );<br />
$timestamp = $last->epoch;<br />
}<br />
else {<br />
# otherwise we don't care<br />
$timestamp = -1;<br />
}<br />
}<br />
else {<br />
# try the start time, then the created time<br />
my $started = DateTime::Format::MySQL->parse_datetime( $ticketObj->Started );<br />
my $created = DateTime::Format::MySQL->parse_datetime( $ticketObj->Created );<br />
<br />
if ( $started->epoch > 0 ) {<br />
$timestamp = $started->epoch;<br />
}<br />
else {<br />
$timestamp = $created->epoch;<br />
}<br />
}<br />
<br />
# if we've gotten this far, and there's still no timestamp,<br />
# then something is terribly wrong<br />
defined( $timestamp ) or $timestamp = -1;<br />
<br />
return( $timestamp );<br />
}<br />
<br />
# The following could be omitted. They're there to allow overrides from Vendor and Local<br />
# but as this isn't a core module, they're just there for completeness :)<br />
eval "require RT::Condition::UntouchedInHours_Vendor";<br />
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Condition/UntouchedInHours_Vendor.pm});<br />
eval "require RT::Condition::UntouchedInHours_Local";<br />
die $@ if ($@ && $@ !~ qr{^Can't locate RT/Condition/UntouchedInHours_Local.pm});<br />
<br />
1;<br />
<br />
Note that *IsApplicable* returns the epoch time of the most recent ticket update or 0; this means that you can call this condition from inside a template and then use *RT::Date::AgeAsString* to generate a human-readable representation of how long the ticket has gone without response.<br />
<br />
Note that this version works with RT 4.0.1 by editing the two instances of RT::Condition::Generic to RT::Condition</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=LowHangingFruit&diff=26462LowHangingFruit2017-01-08T18:55:19Z<p>Barton: /* Low Hanging Fruit */</p>
<hr />
<div>== Low Hanging Fruit ==<br />
<br />
Code block cleanup<br />
<br />
The previous version of the rt-wiki used a single space indent, sometimes surrounded by <code>&lt;nowiki&gt;</code> tags to delimit code blocks. Media-wiki uses a four space indent to delimit code. The old style does not correctly format the first line of the code block.<br />
<br />
The four space indent also makes the code literal, so you don't have to add html entities for greather than and less than.<br />
<br />
Old:<br />
<br />
&lt;%INIT&gt;<br />
$$skip = 1 if $Transaction-&gt;Creator == $RT::SystemUser-&gt;id;<br />
&lt;/%INIT&gt;<br />
&lt;%ARGS&gt;<br />
$Transaction =&gt; undef<br />
$skip =&gt; undef<br />
&lt;/%ARGS&gt;<br />
<br />
New:<br />
<br />
<%INIT><br />
$$skip = 1 if $Transaction->Creator == $RT::SystemUser->id;<br />
</%INIT><br />
<%ARGS><br />
$Transaction => undef<br />
$skip => undef<br />
</%ARGS><br />
<br />
Note that you will have to turn html entities back into their rendered forms. I recommend pasting the code block into vim, and running the following substitutions:<br />
<br />
:%s/&amp;/\&/g<br />
:%s/&lt;/</g<br />
:%s/&gt;/>/g</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=CustomizingWithCallbacks&diff=26461CustomizingWithCallbacks2017-01-08T18:46:24Z<p>Barton: /* GaryOberbrunner -- clean up code block */</p>
<hr />
<div>= Callbacks =<br />
<br />
== Introduction ==<br />
<br />
RT uses Callbacks for adding extensions into the Web GUI without modifying html code. Wikipedia defines a callback as “executable code that is passed as an argument to other code. It allows a lower-level software layer to call a subroutine (or function) defined in a higher-level layer." So callback in RT is a code that you can put into right place and it will be called when a user opens a page.<br />
<br />
Callbacks are called on different places and have to be placed into directories<br />
<br />
<rt root>/local/html/Callbacks/<any directory>/<normal path to html-page>/<CallbackName><br />
<br />
<br />
* &lt;rt root&gt; - we suppose you know where your RT is installed<br />
* local - local directory for your customizations, [[CustomizingWithLocalDir]].<br />
* html - directory with Mason components.<br />
* Callbacks - directory for your Callbacks, create if it doesn't exist. It's Callbacks (lowercase "b") not CallBacks (uppercase "B"), not callbacks.<br />
* &lt;any directory&gt; - one directory with any name you like. Call it MyCallbacks, his_callbacks or boo. The assumption is that you will group your callbacks, based on logic of your choosing. You can have many different callback groups, and the callback will be run for each of them.<br />
* &lt;normal path to html-page&gt; - if a call you want to hook on is in <code>html/X/Y.html</code> file then you should create <code>X/Y.html</code> directory.<br />
* &lt;CallbackName&gt; - name of the callback, each page may have multiple callbacks. By default is 'Default', but might be different. Read more about names below.<br />
<br />
Places where callbacks are called look in the following way (RT 3.8):<br />
<br />
$m->callback(<br />
TicketObj => $TicketObj,<br />
ARGSRef => \%ARGS,<br />
CallbackName => 'Initial',<br />
);<br />
<br />
This is example from Ticket/Display.html in RT 3.8.7, full path to your code may look like this:<br />
<br />
/opt/rt3/local/html/Callbacks/MyCallbacks/Ticket/Display.html/Initial<br />
<br />
Arguments passed to callback function are passed into your code and you can use them to explore situation and modify behaviour.<br />
<br />
== Finding callbacks ==<br />
<br />
You can find all callbacks using grep command:<br />
<br />
cd /opt/rt3/<br />
find share/html | xargs grep '\-&gt;callback'<br />
<br />
In RT 3.6 and older syntax is slightly different, old syntax is still valid and supported:<br />
<br />
cd /opt/rt3/<br />
find share/html | xargs grep 'Elements/Callback'<br />
<br />
In RT 4.2.x these are most of them: [[RT_4.2_Callbacks]]<br />
<br />
In RT-Assets 1.01 these are most of them: [[RT-Assets_1.01_Callbacks]]<br />
<br />
== CallbackName ==<br />
<br />
Each Mason component may call multiple callbacks, so each callback has a name. The name of the callback you figure out from arguments used to call $m-&gt;callback. Understandably, the argument to define a callback name is 'CallbackName' and if it's absent then 'Default' is used.<br />
<br />
For example, the following callback call in Modify.html lacks a name, so its name (by default) is Default<br />
<br />
$m->callback( TicketObj => $TicketObj, CustomFields => $CustomFields, ARGSRef => \%ARGS );<br />
<br />
== Sample callbacks ==<br />
<br />
* [http://page.mi.fu-berlin.de/~pape/rt3/Callbacks/ Samples] from [[DirkPape]].<br />
* [[AddCustomStyleSheet]]<br />
* [[HideTransactions]]: Hide all transactions created by the system user.<br />
* [[ShowPerQueueInstructions]]<br />
* [[RequireCFResolve]]: Require CF value before resolve<br />
* [[ToggleCFs]]: Hide certain Custom Fields unless a "control" CF is set to a specific value. Allows decluttering the user interface in the common case and exposes additional detail (CFs) when needed.<br />
<br />
== Comments ==<br />
<br />
There are some drawbacks, when customizing RT with the "Local" principle: If you have many customizations it is difficult to propagate customizations across version changes. This is mainly because<br />
<br />
* when using the 'local' directory, you overlay '''files'''. If the original file is changed in a new release, e. g. a bug is fixed or a feature is added, you will not profit from this changes immediately, because your overlay is used.<br />
* when using a XXX_Local.pm, you overlay '''methods''' and the same drawback as above will hit you if the method has been changed across releases.<br />
<br />
For both customisation methods hold: They are not local enough! If you overlay, it might be possible that you overlay code (that you did not change) from earlier versions, that have been corrected or adopted to other changes in new versions and that is not compatible with the new version. Hence version upgrades may be complicated. I added two Sections above with customization methods I prefer, because we do many customizations, these are Patches and Callbacks. --[[DirkPape]]<br />
<br />
==== GaryOberbrunner ====<br />
<br />
Here's a sample [[ShowMessageStanza]] callback. Put this in /opt/rt3/share/html/Callbacks/*/Ticket/Elements/ShowMessageStanza/Default :<br />
<br />
<%init><br />
my $val = $$content;<br />
use bytes;<br />
# Auto link 12-digit hex strings to a search page<br />
$val =~ s{[0-9a-f]{12}}{<a href="http://my.example.com/search?$&">$&<\/a>}gi;<br />
$$content = $val;<br />
</%init><br />
<%args><br />
$content => undef<br />
</%args><br />
<br />
<br />
Note that the stanza will appear in $$content, you just modify it in place. Thanks to Toby Darling for the code!<br />
<br />
==Troubleshooting==<br />
Did you clear your Mason cache? (See [[ClearMasonCache|CleanMasonCache]])<br />
<br />
Did you restart your webserver process?<br />
<br />
Are your Mason component settings accurate (in the web UI, visit Tools -> System Configuration and scroll down)?<br />
<br />
Are your file and directory permissions for your new callback set properly?<br />
<br />
Are you sure you have your callback arguments correct? Beware 'TicketObj' vs. 'Ticket' being passed!</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=CustomizingWithCallbacks&diff=26460CustomizingWithCallbacks2017-01-08T18:38:58Z<p>Barton: /* Introduction */</p>
<hr />
<div>= Callbacks =<br />
<br />
== Introduction ==<br />
<br />
RT uses Callbacks for adding extensions into the Web GUI without modifying html code. Wikipedia defines a callback as “executable code that is passed as an argument to other code. It allows a lower-level software layer to call a subroutine (or function) defined in a higher-level layer." So callback in RT is a code that you can put into right place and it will be called when a user opens a page.<br />
<br />
Callbacks are called on different places and have to be placed into directories<br />
<br />
<rt root>/local/html/Callbacks/<any directory>/<normal path to html-page>/<CallbackName><br />
<br />
<br />
* &lt;rt root&gt; - we suppose you know where your RT is installed<br />
* local - local directory for your customizations, [[CustomizingWithLocalDir]].<br />
* html - directory with Mason components.<br />
* Callbacks - directory for your Callbacks, create if it doesn't exist. It's Callbacks (lowercase "b") not CallBacks (uppercase "B"), not callbacks.<br />
* &lt;any directory&gt; - one directory with any name you like. Call it MyCallbacks, his_callbacks or boo. The assumption is that you will group your callbacks, based on logic of your choosing. You can have many different callback groups, and the callback will be run for each of them.<br />
* &lt;normal path to html-page&gt; - if a call you want to hook on is in <code>html/X/Y.html</code> file then you should create <code>X/Y.html</code> directory.<br />
* &lt;CallbackName&gt; - name of the callback, each page may have multiple callbacks. By default is 'Default', but might be different. Read more about names below.<br />
<br />
Places where callbacks are called look in the following way (RT 3.8):<br />
<br />
$m->callback(<br />
TicketObj => $TicketObj,<br />
ARGSRef => \%ARGS,<br />
CallbackName => 'Initial',<br />
);<br />
<br />
This is example from Ticket/Display.html in RT 3.8.7, full path to your code may look like this:<br />
<br />
/opt/rt3/local/html/Callbacks/MyCallbacks/Ticket/Display.html/Initial<br />
<br />
Arguments passed to callback function are passed into your code and you can use them to explore situation and modify behaviour.<br />
<br />
== Finding callbacks ==<br />
<br />
You can find all callbacks using grep command:<br />
<br />
cd /opt/rt3/<br />
find share/html | xargs grep '\-&gt;callback'<br />
<br />
In RT 3.6 and older syntax is slightly different, old syntax is still valid and supported:<br />
<br />
cd /opt/rt3/<br />
find share/html | xargs grep 'Elements/Callback'<br />
<br />
In RT 4.2.x these are most of them: [[RT_4.2_Callbacks]]<br />
<br />
In RT-Assets 1.01 these are most of them: [[RT-Assets_1.01_Callbacks]]<br />
<br />
== CallbackName ==<br />
<br />
Each Mason component may call multiple callbacks, so each callback has a name. The name of the callback you figure out from arguments used to call $m-&gt;callback. Understandably, the argument to define a callback name is 'CallbackName' and if it's absent then 'Default' is used.<br />
<br />
For example, the following callback call in Modify.html lacks a name, so its name (by default) is Default<br />
<br />
$m->callback( TicketObj => $TicketObj, CustomFields => $CustomFields, ARGSRef => \%ARGS );<br />
<br />
== Sample callbacks ==<br />
<br />
* [http://page.mi.fu-berlin.de/~pape/rt3/Callbacks/ Samples] from [[DirkPape]].<br />
* [[AddCustomStyleSheet]]<br />
* [[HideTransactions]]: Hide all transactions created by the system user.<br />
* [[ShowPerQueueInstructions]]<br />
* [[RequireCFResolve]]: Require CF value before resolve<br />
* [[ToggleCFs]]: Hide certain Custom Fields unless a "control" CF is set to a specific value. Allows decluttering the user interface in the common case and exposes additional detail (CFs) when needed.<br />
<br />
== Comments ==<br />
<br />
There are some drawbacks, when customizing RT with the "Local" principle: If you have many customizations it is difficult to propagate customizations across version changes. This is mainly because<br />
<br />
* when using the 'local' directory, you overlay '''files'''. If the original file is changed in a new release, e. g. a bug is fixed or a feature is added, you will not profit from this changes immediately, because your overlay is used.<br />
* when using a XXX_Local.pm, you overlay '''methods''' and the same drawback as above will hit you if the method has been changed across releases.<br />
<br />
For both customisation methods hold: They are not local enough! If you overlay, it might be possible that you overlay code (that you did not change) from earlier versions, that have been corrected or adopted to other changes in new versions and that is not compatible with the new version. Hence version upgrades may be complicated. I added two Sections above with customization methods I prefer, because we do many customizations, these are Patches and Callbacks. --[[DirkPape]]<br />
<br />
==== GaryOberbrunner ====<br />
<br />
Here's a sample [[ShowMessageStanza]] callback. Put this in<br />
<br />
<nowiki>/opt/rt3/share/html/Callbacks/*/Ticket/Elements/ShowMessageStanza/Default :<br />
<br />
&lt;%init&gt;<br />
my $val = $$content;<br />
use bytes;<br />
# Auto link 12-digit hex strings to a search page<br />
$val =~ s{[0-9a-f]{12}}{&lt;a href="http://my.example.com/search?$&amp;"&gt;$&amp;&lt;\/a&gt;}gi;<br />
$$content = $val;<br />
&lt;/%init&gt;<br />
&lt;%args&gt;<br />
$content =&gt; undef<br />
&lt;/%args&gt;<br />
<br />
</nowiki><br />
<br />
Note that the stanza will appear in $$content, you just modify it in place. Thanks to Toby Darling for the code!<br />
<br />
<br />
<br />
==Troubleshooting==<br />
Did you clear your Mason cache? (See [[ClearMasonCache|CleanMasonCache]])<br />
<br />
Did you restart your webserver process?<br />
<br />
Are your Mason component settings accurate (in the web UI, visit Tools -> System Configuration and scroll down)?<br />
<br />
Are your file and directory permissions for your new callback set properly?<br />
<br />
Are you sure you have your callback arguments correct? Beware 'TicketObj' vs. 'Ticket' being passed!</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=CustomizingWithCallbacks&diff=26459CustomizingWithCallbacks2017-01-08T18:35:51Z<p>Barton: /* Finding callbacks -- code block reformatting */</p>
<hr />
<div>= Callbacks =<br />
<br />
== Introduction ==<br />
<br />
RT uses Callbacks for adding extensions into the Web GUI without modifying html code. Wikipedia defines a callback as “executable code that is passed as an argument to other code. It allows a lower-level software layer to call a subroutine (or function) defined in a higher-level layer." So callback in RT is a code that you can put into right place and it will be called when a user opens a page.<br />
<br />
Callbacks are called on different places and have to be placed into directories &lt;rt root&gt;/local/html/Callbacks/&lt;any directory&gt;/&lt;normal path to html-page&gt;/&lt;CallbackName&gt;.<br />
<br />
* &lt;rt root&gt; - we suppose you know where your RT is installed<br />
* local - local directory for your customizations, [[CustomizingWithLocalDir]].<br />
* html - directory with Mason components.<br />
* Callbacks - directory for your Callbacks, create if it doesn't exist. It's Callbacks (lowercase "b") not CallBacks (uppercase "B"), not callbacks.<br />
* &lt;any directory&gt; - one directory with any name you like. Call it MyCallbacks, his_callbacks or boo. The assumption is that you will group your callbacks, based on logic of your choosing. You can have many different callback groups, and the callback will be run for each of them.<br />
* &lt;normal path to html-page&gt; - if a call you want to hook on is in <code>html/X/Y.html</code> file then you should create <code>X/Y.html</code> directory.<br />
* &lt;CallbackName&gt; - name of the callback, each page may have multiple callbacks. By default is 'Default', but might be different. Read more about names below.<br />
<br />
Places where callbacks are called look in the following way (RT 3.8):<br />
<br />
$m->callback(<br />
TicketObj => $TicketObj,<br />
ARGSRef => \%ARGS,<br />
CallbackName => 'Initial',<br />
);<br />
<br />
This is example from Ticket/Display.html in RT 3.8.7, full path to your code may look like this:<br />
<br />
/opt/rt3/local/html/Callbacks/MyCallbacks/Ticket/Display.html/Initial<br />
<br />
Arguments passed to callback function are passed into your code and you can use them to explore situation and modify behaviour.<br />
<br />
== Finding callbacks ==<br />
<br />
You can find all callbacks using grep command:<br />
<br />
cd /opt/rt3/<br />
find share/html | xargs grep '\-&gt;callback'<br />
<br />
In RT 3.6 and older syntax is slightly different, old syntax is still valid and supported:<br />
<br />
cd /opt/rt3/<br />
find share/html | xargs grep 'Elements/Callback'<br />
<br />
In RT 4.2.x these are most of them: [[RT_4.2_Callbacks]]<br />
<br />
In RT-Assets 1.01 these are most of them: [[RT-Assets_1.01_Callbacks]]<br />
<br />
== CallbackName ==<br />
<br />
Each Mason component may call multiple callbacks, so each callback has a name. The name of the callback you figure out from arguments used to call $m-&gt;callback. Understandably, the argument to define a callback name is 'CallbackName' and if it's absent then 'Default' is used.<br />
<br />
For example, the following callback call in Modify.html lacks a name, so its name (by default) is Default<br />
<br />
$m->callback( TicketObj => $TicketObj, CustomFields => $CustomFields, ARGSRef => \%ARGS );<br />
<br />
== Sample callbacks ==<br />
<br />
* [http://page.mi.fu-berlin.de/~pape/rt3/Callbacks/ Samples] from [[DirkPape]].<br />
* [[AddCustomStyleSheet]]<br />
* [[HideTransactions]]: Hide all transactions created by the system user.<br />
* [[ShowPerQueueInstructions]]<br />
* [[RequireCFResolve]]: Require CF value before resolve<br />
* [[ToggleCFs]]: Hide certain Custom Fields unless a "control" CF is set to a specific value. Allows decluttering the user interface in the common case and exposes additional detail (CFs) when needed.<br />
<br />
== Comments ==<br />
<br />
There are some drawbacks, when customizing RT with the "Local" principle: If you have many customizations it is difficult to propagate customizations across version changes. This is mainly because<br />
<br />
* when using the 'local' directory, you overlay '''files'''. If the original file is changed in a new release, e. g. a bug is fixed or a feature is added, you will not profit from this changes immediately, because your overlay is used.<br />
* when using a XXX_Local.pm, you overlay '''methods''' and the same drawback as above will hit you if the method has been changed across releases.<br />
<br />
For both customisation methods hold: They are not local enough! If you overlay, it might be possible that you overlay code (that you did not change) from earlier versions, that have been corrected or adopted to other changes in new versions and that is not compatible with the new version. Hence version upgrades may be complicated. I added two Sections above with customization methods I prefer, because we do many customizations, these are Patches and Callbacks. --[[DirkPape]]<br />
<br />
==== GaryOberbrunner ====<br />
<br />
Here's a sample [[ShowMessageStanza]] callback. Put this in<br />
<br />
<nowiki>/opt/rt3/share/html/Callbacks/*/Ticket/Elements/ShowMessageStanza/Default :<br />
<br />
&lt;%init&gt;<br />
my $val = $$content;<br />
use bytes;<br />
# Auto link 12-digit hex strings to a search page<br />
$val =~ s{[0-9a-f]{12}}{&lt;a href="http://my.example.com/search?$&amp;"&gt;$&amp;&lt;\/a&gt;}gi;<br />
$$content = $val;<br />
&lt;/%init&gt;<br />
&lt;%args&gt;<br />
$content =&gt; undef<br />
&lt;/%args&gt;<br />
<br />
</nowiki><br />
<br />
Note that the stanza will appear in $$content, you just modify it in place. Thanks to Toby Darling for the code!<br />
<br />
<br />
<br />
==Troubleshooting==<br />
Did you clear your Mason cache? (See [[ClearMasonCache|CleanMasonCache]])<br />
<br />
Did you restart your webserver process?<br />
<br />
Are your Mason component settings accurate (in the web UI, visit Tools -> System Configuration and scroll down)?<br />
<br />
Are your file and directory permissions for your new callback set properly?<br />
<br />
Are you sure you have your callback arguments correct? Beware 'TicketObj' vs. 'Ticket' being passed!</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=CustomizingWithCallbacks&diff=26458CustomizingWithCallbacks2017-01-08T18:34:54Z<p>Barton: /* reformat code blocks */</p>
<hr />
<div>= Callbacks =<br />
<br />
== Introduction ==<br />
<br />
RT uses Callbacks for adding extensions into the Web GUI without modifying html code. Wikipedia defines a callback as “executable code that is passed as an argument to other code. It allows a lower-level software layer to call a subroutine (or function) defined in a higher-level layer." So callback in RT is a code that you can put into right place and it will be called when a user opens a page.<br />
<br />
Callbacks are called on different places and have to be placed into directories &lt;rt root&gt;/local/html/Callbacks/&lt;any directory&gt;/&lt;normal path to html-page&gt;/&lt;CallbackName&gt;.<br />
<br />
* &lt;rt root&gt; - we suppose you know where your RT is installed<br />
* local - local directory for your customizations, [[CustomizingWithLocalDir]].<br />
* html - directory with Mason components.<br />
* Callbacks - directory for your Callbacks, create if it doesn't exist. It's Callbacks (lowercase "b") not CallBacks (uppercase "B"), not callbacks.<br />
* &lt;any directory&gt; - one directory with any name you like. Call it MyCallbacks, his_callbacks or boo. The assumption is that you will group your callbacks, based on logic of your choosing. You can have many different callback groups, and the callback will be run for each of them.<br />
* &lt;normal path to html-page&gt; - if a call you want to hook on is in <code>html/X/Y.html</code> file then you should create <code>X/Y.html</code> directory.<br />
* &lt;CallbackName&gt; - name of the callback, each page may have multiple callbacks. By default is 'Default', but might be different. Read more about names below.<br />
<br />
Places where callbacks are called look in the following way (RT 3.8):<br />
<br />
$m->callback(<br />
TicketObj => $TicketObj,<br />
ARGSRef => \%ARGS,<br />
CallbackName => 'Initial',<br />
);<br />
<br />
This is example from Ticket/Display.html in RT 3.8.7, full path to your code may look like this:<br />
<br />
/opt/rt3/local/html/Callbacks/MyCallbacks/Ticket/Display.html/Initial<br />
<br />
Arguments passed to callback function are passed into your code and you can use them to explore situation and modify behaviour.<br />
<br />
== Finding callbacks ==<br />
<br />
You can find all callbacks using grep command:<br />
<br />
cd /opt/rt3/<br />
find share/html | xargs grep '\-&gt;callback'<br />
<br />
In RT 3.6 and older syntax is slightly different, old syntax is still valid and supported:<br />
<br />
cd /opt/rt3/<br />
find share/html | xargs grep 'Elements/Callback'<br />
<br />
In RT 4.2.x these are most of them: [[RT_4.2_Callbacks]]<br />
<br />
In RT-Assets 1.01 these are most of them: [[RT-Assets_1.01_Callbacks]]<br />
<br />
== CallbackName ==<br />
<br />
Each Mason component may call multiple callbacks, so each callback has a name. The name of the callback you figure out from arguments used to call $m-&gt;callback. Understandably, the argument to define a callback name is 'CallbackName' and if it's absent then 'Default' is used.<br />
<br />
For example, the following callback call in Modify.html lacks a name, so its name (by default) is Default<br />
<br />
$m->callback( TicketObj => $TicketObj, CustomFields => $CustomFields, ARGSRef => \%ARGS );<br />
<br />
== Sample callbacks ==<br />
<br />
* [http://page.mi.fu-berlin.de/~pape/rt3/Callbacks/ Samples] from [[DirkPape]].<br />
* [[AddCustomStyleSheet]]<br />
* [[HideTransactions]]: Hide all transactions created by the system user.<br />
* [[ShowPerQueueInstructions]]<br />
* [[RequireCFResolve]]: Require CF value before resolve<br />
* [[ToggleCFs]]: Hide certain Custom Fields unless a "control" CF is set to a specific value. Allows decluttering the user interface in the common case and exposes additional detail (CFs) when needed.<br />
<br />
== Comments ==<br />
<br />
There are some drawbacks, when customizing RT with the "Local" principle: If you have many customizations it is difficult to propagate customizations across version changes. This is mainly because<br />
<br />
* when using the 'local' directory, you overlay '''files'''. If the original file is changed in a new release, e. g. a bug is fixed or a feature is added, you will not profit from this changes immediately, because your overlay is used.<br />
* when using a XXX_Local.pm, you overlay '''methods''' and the same drawback as above will hit you if the method has been changed across releases.<br />
<br />
For both customisation methods hold: They are not local enough! If you overlay, it might be possible that you overlay code (that you did not change) from earlier versions, that have been corrected or adopted to other changes in new versions and that is not compatible with the new version. Hence version upgrades may be complicated. I added two Sections above with customization methods I prefer, because we do many customizations, these are Patches and Callbacks. --[[DirkPape]]<br />
<br />
==== GaryOberbrunner ====<br />
<br />
Here's a sample [[ShowMessageStanza]] callback. Put this in<br />
<br />
<nowiki>/opt/rt3/share/html/Callbacks/*/Ticket/Elements/ShowMessageStanza/Default :<br />
<br />
&lt;%init&gt;<br />
my $val = $$content;<br />
use bytes;<br />
# Auto link 12-digit hex strings to a search page<br />
$val =~ s{[0-9a-f]{12}}{&lt;a href="http://my.example.com/search?$&amp;"&gt;$&amp;&lt;\/a&gt;}gi;<br />
$$content = $val;<br />
&lt;/%init&gt;<br />
&lt;%args&gt;<br />
$content =&gt; undef<br />
&lt;/%args&gt;<br />
<br />
</nowiki><br />
<br />
Note that the stanza will appear in $$content, you just modify it in place. Thanks to Toby Darling for the code!<br />
<br />
<br />
<br />
==Troubleshooting==<br />
Did you clear your Mason cache? (See [[ClearMasonCache|CleanMasonCache]])<br />
<br />
Did you restart your webserver process?<br />
<br />
Are your Mason component settings accurate (in the web UI, visit Tools -> System Configuration and scroll down)?<br />
<br />
Are your file and directory permissions for your new callback set properly?<br />
<br />
Are you sure you have your callback arguments correct? Beware 'TicketObj' vs. 'Ticket' being passed!</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=LowHangingFruit&diff=26457LowHangingFruit2017-01-08T18:28:48Z<p>Barton: /* Low Hanging Fruit */</p>
<hr />
<div>== Low Hanging Fruit ==<br />
<br />
Code block cleanup<br />
<br />
The previous version of the rt-wiki used a single space indent, sometimes surrounded by <code>&lt;nowiki&gt;</code> tags to delimit code blocks. Media-wiki uses a four space indent to delimit code. The old style does not correctly format the first line of the code block.<br />
<br />
The four space indent also makes the code literal, so you don't have to add html entities for greather than and less than.<br />
<br />
Old:<br />
<br />
&lt;%INIT&gt;<br />
$$skip = 1 if $Transaction-&gt;Creator == $RT::SystemUser-&gt;id;<br />
&lt;/%INIT&gt;<br />
&lt;%ARGS&gt;<br />
$Transaction =&gt; undef<br />
$skip =&gt; undef<br />
&lt;/%ARGS&gt;<br />
<br />
New:<br />
<br />
<%INIT><br />
$$skip = 1 if $Transaction->Creator == $RT::SystemUser->id;<br />
</%INIT><br />
<%ARGS><br />
$Transaction => undef<br />
$skip => undef<br />
</%ARGS></div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=LowHangingFruit&diff=26456LowHangingFruit2017-01-08T18:28:27Z<p>Barton: Created page with "== Low Hanging Fruit == Code block cleanup The previous version of the rt-wiki used a single space indent, sometimes surrounded by <code>&lt;nowiki&gt;</code> tags to delimi..."</p>
<hr />
<div>== Low Hanging Fruit ==<br />
<br />
Code block cleanup<br />
<br />
The previous version of the rt-wiki used a single space indent, sometimes surrounded by <code>&lt;nowiki&gt;</code> tags to delimit code blocks. Media-wiki uses a four space indent to delimit code. The old style does not correctly format the first line of the code block.<br />
<br />
The for space indent also makes the code literal, so you don't have to add html entities for greather than and less than.<br />
<br />
Old:<br />
<br />
&lt;%INIT&gt;<br />
$$skip = 1 if $Transaction-&gt;Creator == $RT::SystemUser-&gt;id;<br />
&lt;/%INIT&gt;<br />
&lt;%ARGS&gt;<br />
$Transaction =&gt; undef<br />
$skip =&gt; undef<br />
&lt;/%ARGS&gt;<br />
<br />
New:<br />
<br />
<%INIT><br />
$$skip = 1 if $Transaction->Creator == $RT::SystemUser->id;<br />
</%INIT><br />
<%ARGS><br />
$Transaction => undef<br />
$skip => undef<br />
</%ARGS></div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=UpdateTheWiki&diff=26455UpdateTheWiki2017-01-08T18:27:04Z<p>Barton: </p>
<hr />
<div>Updating the Wiki is very easy.<br />
<br />
=== To edit existing pages: ===<br />
<br />
* click the Edit link at the top of the page or on any section<br />
* edit the page contents and click save<br />
<br />
=== To add new pages: ===<br />
<br />
* click the edit link on the page where you want to add the first link to the new page<br />
* add [[CamelCaseNameOfNewPage]] to the text of the page and click save. ([http://en.wikipedia.org/wiki/CamelCase What's CamelCase?]).<br />
* you should see [[CamelCaseNameOfNewPage]] as a red link<br />
* click this link and you will see a create box for the new page<br />
<br />
If name of the new page doesn't match [[CamelCase]] notation, like REST or Ticket use [[REST]] or [[Ticket]].<br />
<br />
You can use the following trick as well:<br />
<br />
* in the URL string of your browser write http://requesttracker.wikia.com/wiki/NameOfNewPage<br />
* hit enter, and yahoo!! you're editing new page, or seeing a page that already exists, and you can edit it :)<br />
* This trick has a trade-off, as a new page is not linked to from any other page. People can only find it with the search box, so you have to add links later.<br />
<br />
Additional information:<br />
<br />
* [[WikiWishList]] - wish list for the RT Wiki<br />
* [[LowHangingFruit]] - improvements to wiki formatting which do not require extensive knowledge of RT.</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=WikiWishList&diff=26454WikiWishList2017-01-08T18:04:43Z<p>Barton: /* Wiki Editors */</p>
<hr />
<div>(If you're a regular editor, you're probably seeing this; scroll to the last section, please? --Baylink)<br />
<br />
== Wiki Wishlist ==<br />
<br />
* I wish there was a manual for end-users, i.e. for non-privileged users. I feel that this wiki and the book are aimed at towards privileged users, administrators and developers. Of course a "real" end-user manual would be dependent on the configuration of the RT site, but a framework and a description of basic concepts and actions would still be nice. More generally, manuals/wiki for the 4 differents publics should be better separated. -- great great book [http://shop.oreilly.com/product/9780596006686.do RT Essentials O'Reilly Media] for ALL kinds of users that would answer your request, [[User:Lnaia|Lnaia]]<br />
* Search is just useless.<br />
** We have a trouble ticket open with Wikia. [[User:Tsibley|Tsibley]] 20:34, December 10, 2010 (UTC)<br />
* Important areas of documentation are just missing, like [[TicketSQL]].<br />
<br />
* Much of the documentation here is old and not relevant to the current version. The individual artices are not grouped in any version order and have no indication of versions. I think a version number(s) should be indicated on each article and the index as well if all the articles are put together as they are now. --Stephen Hancock<br />
** I'm working on the [[UserManual]] as we speak; my approach is "make it current for 3.8, and just warn people that if they're using an older version, some things might be missing or work differently". I'm not aware of any wiki that's really tuned for the multiple versions thing... though if we were '''really''' dedicated (read: if BPS were '''paying me to do it''' :-), I might try to adapt the "Which episode have you seen?" code for [[MediaWiki]] that the Veronica Mars site used to use. --Baylink<br />
<br />
* Searching this wiki doesn't pull back expected results. eg: Searching for "[[WishList]] Wiki" or "Reports Time" returns no results. When its hard to find information by following links the search should be better at finding relevant pages for you.<br />
<br />
* A knowledge base, when you post a question you can see prior questions and their answers... if the prior solutions do not work, continue with the ticket.<br />
** You can't '''quite''' get to here using a wiki engine, but I'm commencing to assemble Q&amp;A onto the [[ManualProblems]] page from everywhere I can find them. I encourage assistance from others. :-) --Baylink<br />
<br />
* list of places to get themes for RT<br />
** As I know nobody have shared theme, yet. --[[RuslanZakirov]]<br />
<br />
* Why are there no questions/answers related to RTFM? The "manual" here does not include the most important info--how to get articles into the RTFM system<br />
** This will be the subject of the next RT Tutorial, coming soon! -- [[Cassandra]]<br />
<br />
* While many pages do a reasonable job of flagging things that are verison specific, what about flagging things that are deprecated due to their functionality being implemented in more modern versions? -- Jerrad<br />
** I'm trying to note this as I go -- as an example, I refactored the "color status and priority" page to put the 3.8 material up top. --Baylink<br />
<br />
* Why not to use MediaWiki engine? I'm sorry but this engine is so poor (text formatting, front-end etc.).<br />
* When working with other RT users on a same ticket, it would be clever to be able to edit a draft response which has not been sent. Example when I write response I'm not 100% sure is right, I would like another RT user to review and accept or edit current respone.<br />
<br />
== Community Patrol for WiKi Quality ==<br />
<br />
Need some '[[WiKi]]' Moderator, who will keep an eye for 'Recent Change'. Anyone Here...? Maybe... Me ? -- Bauani<br />
<br />
== Things that are done ==<br />
<br />
[http://www.css.washington.edu/wiki/Category:Request_Tracker Wash Uni: Request Tracker]. Both are free. -- [[ChristopherShort]]<br />
<br />
* I would love to know when the latest release of RT will be available for download, on the wiki main page. - [[ErnaJ]]<br />
<br />
* <br />
** I added an "Announcements" section with news about the latest RT release and public training sessions on the Wiki main page. -- [[Cassandra]]<br />
<br />
* I added a new section, [[RTTutorials]], which will feature RT tutorials as they are put up on the blog. -- [[Cassandra]]<br />
<br />
* I added a link to an explanation of [[CamelCase]] to the [[UpdateTheWiki]] page. -- [[Cassandra]]<br />
<br />
* I added a new page explaining the difference between the "Update" and "Save Changes" buttons when you are replying to/commenting on a ticket in the UI. If someone wants to please link this to wherever you think it would be useful--scrips about notification, maybe? -- [[Cassandra]]<br />
<br />
== Wiki Editors ==<br />
<br />
If you're actively working on the wiki, add your username, and a short note about what you're working on regularly to this list.<br />
<br />
* Baylink - [[UserManual]], [[FAQ]], [[HomePage]]<br />
* [[BillCole]] - carbon-based antispambot :)<br />
* declaya - Pretty crazy authentification things :) ([[RT4 & Kerberos & SSO & Ubuntu 10.04 & Apache 2 & AD & Windows Server & Adding User Data & a lot of Windows Clients|KerberosAuthentication]])<br />
* [[User:Barton|Barton]] - Reformatting code blocks</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=User:Barton&diff=26453User:Barton2017-01-08T18:02:41Z<p>Barton: Created page with "- Code Janitor - Bash officianado - Perl coder I work for [http://bywatersolutions.com ByWater Solutions]."</p>
<hr />
<div>- Code Janitor<br />
- Bash officianado<br />
- Perl coder<br />
<br />
I work for [http://bywatersolutions.com ByWater Solutions].</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=WikiWishList&diff=26452WikiWishList2017-01-08T17:46:29Z<p>Barton: /* Wiki Editors */</p>
<hr />
<div>(If you're a regular editor, you're probably seeing this; scroll to the last section, please? --Baylink)<br />
<br />
== Wiki Wishlist ==<br />
<br />
* I wish there was a manual for end-users, i.e. for non-privileged users. I feel that this wiki and the book are aimed at towards privileged users, administrators and developers. Of course a "real" end-user manual would be dependent on the configuration of the RT site, but a framework and a description of basic concepts and actions would still be nice. More generally, manuals/wiki for the 4 differents publics should be better separated. -- great great book [http://shop.oreilly.com/product/9780596006686.do RT Essentials O'Reilly Media] for ALL kinds of users that would answer your request, [[User:Lnaia|Lnaia]]<br />
* Search is just useless.<br />
** We have a trouble ticket open with Wikia. [[User:Tsibley|Tsibley]] 20:34, December 10, 2010 (UTC)<br />
* Important areas of documentation are just missing, like [[TicketSQL]].<br />
<br />
* Much of the documentation here is old and not relevant to the current version. The individual artices are not grouped in any version order and have no indication of versions. I think a version number(s) should be indicated on each article and the index as well if all the articles are put together as they are now. --Stephen Hancock<br />
** I'm working on the [[UserManual]] as we speak; my approach is "make it current for 3.8, and just warn people that if they're using an older version, some things might be missing or work differently". I'm not aware of any wiki that's really tuned for the multiple versions thing... though if we were '''really''' dedicated (read: if BPS were '''paying me to do it''' :-), I might try to adapt the "Which episode have you seen?" code for [[MediaWiki]] that the Veronica Mars site used to use. --Baylink<br />
<br />
* Searching this wiki doesn't pull back expected results. eg: Searching for "[[WishList]] Wiki" or "Reports Time" returns no results. When its hard to find information by following links the search should be better at finding relevant pages for you.<br />
<br />
* A knowledge base, when you post a question you can see prior questions and their answers... if the prior solutions do not work, continue with the ticket.<br />
** You can't '''quite''' get to here using a wiki engine, but I'm commencing to assemble Q&amp;A onto the [[ManualProblems]] page from everywhere I can find them. I encourage assistance from others. :-) --Baylink<br />
<br />
* list of places to get themes for RT<br />
** As I know nobody have shared theme, yet. --[[RuslanZakirov]]<br />
<br />
* Why are there no questions/answers related to RTFM? The "manual" here does not include the most important info--how to get articles into the RTFM system<br />
** This will be the subject of the next RT Tutorial, coming soon! -- [[Cassandra]]<br />
<br />
* While many pages do a reasonable job of flagging things that are verison specific, what about flagging things that are deprecated due to their functionality being implemented in more modern versions? -- Jerrad<br />
** I'm trying to note this as I go -- as an example, I refactored the "color status and priority" page to put the 3.8 material up top. --Baylink<br />
<br />
* Why not to use MediaWiki engine? I'm sorry but this engine is so poor (text formatting, front-end etc.).<br />
* When working with other RT users on a same ticket, it would be clever to be able to edit a draft response which has not been sent. Example when I write response I'm not 100% sure is right, I would like another RT user to review and accept or edit current respone.<br />
<br />
== Community Patrol for WiKi Quality ==<br />
<br />
Need some '[[WiKi]]' Moderator, who will keep an eye for 'Recent Change'. Anyone Here...? Maybe... Me ? -- Bauani<br />
<br />
== Things that are done ==<br />
<br />
[http://www.css.washington.edu/wiki/Category:Request_Tracker Wash Uni: Request Tracker]. Both are free. -- [[ChristopherShort]]<br />
<br />
* I would love to know when the latest release of RT will be available for download, on the wiki main page. - [[ErnaJ]]<br />
<br />
* <br />
** I added an "Announcements" section with news about the latest RT release and public training sessions on the Wiki main page. -- [[Cassandra]]<br />
<br />
* I added a new section, [[RTTutorials]], which will feature RT tutorials as they are put up on the blog. -- [[Cassandra]]<br />
<br />
* I added a link to an explanation of [[CamelCase]] to the [[UpdateTheWiki]] page. -- [[Cassandra]]<br />
<br />
* I added a new page explaining the difference between the "Update" and "Save Changes" buttons when you are replying to/commenting on a ticket in the UI. If someone wants to please link this to wherever you think it would be useful--scrips about notification, maybe? -- [[Cassandra]]<br />
<br />
== Wiki Editors ==<br />
<br />
If you're actively working on the wiki, add your username, and a short note about what you're working on regularly to this list.<br />
<br />
* Baylink - [[UserManual]], [[FAQ]], [[HomePage]]<br />
* [[BillCole]] - carbon-based antispambot :)<br />
* declaya - Pretty crazy authentification things :) ([[RT4 & Kerberos & SSO & Ubuntu 10.04 & Apache 2 & AD & Windows Server & Adding User Data & a lot of Windows Clients|KerberosAuthentication]])<br />
* [[User:Barton]] - Reformatting code blocks</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=WikiWishList&diff=26451WikiWishList2017-01-08T17:45:35Z<p>Barton: /* Wiki Editors */</p>
<hr />
<div>(If you're a regular editor, you're probably seeing this; scroll to the last section, please? --Baylink)<br />
<br />
== Wiki Wishlist ==<br />
<br />
* I wish there was a manual for end-users, i.e. for non-privileged users. I feel that this wiki and the book are aimed at towards privileged users, administrators and developers. Of course a "real" end-user manual would be dependent on the configuration of the RT site, but a framework and a description of basic concepts and actions would still be nice. More generally, manuals/wiki for the 4 differents publics should be better separated. -- great great book [http://shop.oreilly.com/product/9780596006686.do RT Essentials O'Reilly Media] for ALL kinds of users that would answer your request, [[User:Lnaia|Lnaia]]<br />
* Search is just useless.<br />
** We have a trouble ticket open with Wikia. [[User:Tsibley|Tsibley]] 20:34, December 10, 2010 (UTC)<br />
* Important areas of documentation are just missing, like [[TicketSQL]].<br />
<br />
* Much of the documentation here is old and not relevant to the current version. The individual artices are not grouped in any version order and have no indication of versions. I think a version number(s) should be indicated on each article and the index as well if all the articles are put together as they are now. --Stephen Hancock<br />
** I'm working on the [[UserManual]] as we speak; my approach is "make it current for 3.8, and just warn people that if they're using an older version, some things might be missing or work differently". I'm not aware of any wiki that's really tuned for the multiple versions thing... though if we were '''really''' dedicated (read: if BPS were '''paying me to do it''' :-), I might try to adapt the "Which episode have you seen?" code for [[MediaWiki]] that the Veronica Mars site used to use. --Baylink<br />
<br />
* Searching this wiki doesn't pull back expected results. eg: Searching for "[[WishList]] Wiki" or "Reports Time" returns no results. When its hard to find information by following links the search should be better at finding relevant pages for you.<br />
<br />
* A knowledge base, when you post a question you can see prior questions and their answers... if the prior solutions do not work, continue with the ticket.<br />
** You can't '''quite''' get to here using a wiki engine, but I'm commencing to assemble Q&amp;A onto the [[ManualProblems]] page from everywhere I can find them. I encourage assistance from others. :-) --Baylink<br />
<br />
* list of places to get themes for RT<br />
** As I know nobody have shared theme, yet. --[[RuslanZakirov]]<br />
<br />
* Why are there no questions/answers related to RTFM? The "manual" here does not include the most important info--how to get articles into the RTFM system<br />
** This will be the subject of the next RT Tutorial, coming soon! -- [[Cassandra]]<br />
<br />
* While many pages do a reasonable job of flagging things that are verison specific, what about flagging things that are deprecated due to their functionality being implemented in more modern versions? -- Jerrad<br />
** I'm trying to note this as I go -- as an example, I refactored the "color status and priority" page to put the 3.8 material up top. --Baylink<br />
<br />
* Why not to use MediaWiki engine? I'm sorry but this engine is so poor (text formatting, front-end etc.).<br />
* When working with other RT users on a same ticket, it would be clever to be able to edit a draft response which has not been sent. Example when I write response I'm not 100% sure is right, I would like another RT user to review and accept or edit current respone.<br />
<br />
== Community Patrol for WiKi Quality ==<br />
<br />
Need some '[[WiKi]]' Moderator, who will keep an eye for 'Recent Change'. Anyone Here...? Maybe... Me ? -- Bauani<br />
<br />
== Things that are done ==<br />
<br />
[http://www.css.washington.edu/wiki/Category:Request_Tracker Wash Uni: Request Tracker]. Both are free. -- [[ChristopherShort]]<br />
<br />
* I would love to know when the latest release of RT will be available for download, on the wiki main page. - [[ErnaJ]]<br />
<br />
* <br />
** I added an "Announcements" section with news about the latest RT release and public training sessions on the Wiki main page. -- [[Cassandra]]<br />
<br />
* I added a new section, [[RTTutorials]], which will feature RT tutorials as they are put up on the blog. -- [[Cassandra]]<br />
<br />
* I added a link to an explanation of [[CamelCase]] to the [[UpdateTheWiki]] page. -- [[Cassandra]]<br />
<br />
* I added a new page explaining the difference between the "Update" and "Save Changes" buttons when you are replying to/commenting on a ticket in the UI. If someone wants to please link this to wherever you think it would be useful--scrips about notification, maybe? -- [[Cassandra]]<br />
<br />
== Wiki Editors ==<br />
<br />
If you're actively working on the wiki, add your username, and a short note about what you're working on regularly to this list.<br />
<br />
* Baylink - [[UserManual]], [[FAQ]], [[HomePage]]<br />
* [[BillCole]] - carbon-based antispambot :)<br />
* declaya - Pretty crazy authentification things :) ([[RT4 & Kerberos & SSO & Ubuntu 10.04 & Apache 2 & AD & Windows Server & Adding User Data & a lot of Windows Clients|KerberosAuthentication]])<br />
* [[barton]] - Reformatting code blocks</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=HideTransactions&diff=26450HideTransactions2017-01-08T17:36:31Z<p>Barton: /*Reforemat code snippit on "Do not hide on History.html page" */</p>
<hr />
<div>= Hiding transactions in tickets' history =<br />
<br />
== Introdduction ==<br />
<br />
You '''should be''' familiar with [[CustomizingWithCallbacks]] as all examples here are based on 'SkipTransaction' callback in Ticket/Elements/ShowHistory Mason component. Create a Callback 'SkipTransaction' in local/html/Callbacks/&lt;MyCallbacks&gt;/Ticket/Elements/ShowHistory/SkipTransaction and pick code below.<br />
<br />
'''For RT 4.2.0 and above '''Ticket/Elements/ShowHistory no longer exists. You will need to hook Elements/ShowHistory's SkipTransaction instead. Keep in mind that this means your transactions may apply to users or queues in addition to tickets and you should tread carefully.<br />
<br />
SkipTransaction callback allows your code to set $$skip variable if you want to skip the current transaction.<br />
<br />
== Minimal example ==<br />
<br />
This is minimal example as starting point that hides all transactions created by the system user.<br />
<br />
<%INIT><br />
$$skip = 1 if $Transaction->Creator == $RT::SystemUser->id;<br />
</%INIT><br />
<%ARGS><br />
$Transaction => undef<br />
$skip => undef<br />
</%ARGS><br />
<br />
== Sane template for your custom code ==<br />
<br />
<code><br />
<%INIT><br />
# do nothing if transaction is already flagged for skipping<br />
# yes, this is possible, you may have many callbacks that<br />
# skip using different conditions<br />
return if $$skip;<br />
<br />
# do nothing if it's not system user<br />
return unless $Transaction->Creator == $RT::SystemUser->id;<br />
<br />
# this is not good idea to skip some transaction types<br />
# even if those are created by system user<br />
return if $SHOW{ $Transaction->Type };<br />
<br />
...<br />
here add your additional conditions<br />
...<br />
<br />
</%INIT><br />
<%ONCE><br />
my %SHOW = map { $_ => 1} qw(<br />
Create Comment Correspond<br />
EmailRecord CommentEmailRecord<br />
);<br />
</%ONCE><br />
<%ARGS><br />
$Transaction => undef<br />
$skip => undef<br />
</%ARGS><br />
</code><br />
<br />
== Additional code snippets ==<br />
<br />
=== Do not hide on History.html page ===<br />
<br />
If you'd like to have an abbreviated history on the main ticket display, but would like the full history in the History tab display, then add the following:<br />
<br />
...<br />
# do nothing if we're on history page<br />
return if $r->uri =~ /History\.html/;<br />
...<br />
<br />
== RT::Extension::HistoryFilter ==<br />
<br />
I created an extension where you can define which transaction types are shown on the ticket display page. The ticket history page shows always the full history. You can find it at github: [http://github.com/cloos/rt-extension-briefhistory http://github.com/cloos/rt-extension-historyfilter]<br />
<br />
== See also ==<br />
<br />
[[CustomizingWithCallbacks]]</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=HideTransactions&diff=26449HideTransactions2017-01-08T17:33:47Z<p>Barton: /*Reformat code block for "Sane template for your custom code" */</p>
<hr />
<div>= Hiding transactions in tickets' history =<br />
<br />
== Introdduction ==<br />
<br />
You '''should be''' familiar with [[CustomizingWithCallbacks]] as all examples here are based on 'SkipTransaction' callback in Ticket/Elements/ShowHistory Mason component. Create a Callback 'SkipTransaction' in local/html/Callbacks/&lt;MyCallbacks&gt;/Ticket/Elements/ShowHistory/SkipTransaction and pick code below.<br />
<br />
'''For RT 4.2.0 and above '''Ticket/Elements/ShowHistory no longer exists. You will need to hook Elements/ShowHistory's SkipTransaction instead. Keep in mind that this means your transactions may apply to users or queues in addition to tickets and you should tread carefully.<br />
<br />
SkipTransaction callback allows your code to set $$skip variable if you want to skip the current transaction.<br />
<br />
== Minimal example ==<br />
<br />
This is minimal example as starting point that hides all transactions created by the system user.<br />
<br />
<%INIT><br />
$$skip = 1 if $Transaction->Creator == $RT::SystemUser->id;<br />
</%INIT><br />
<%ARGS><br />
$Transaction => undef<br />
$skip => undef<br />
</%ARGS><br />
<br />
== Sane template for your custom code ==<br />
<br />
<code><br />
<%INIT><br />
# do nothing if transaction is already flagged for skipping<br />
# yes, this is possible, you may have many callbacks that<br />
# skip using different conditions<br />
return if $$skip;<br />
<br />
# do nothing if it's not system user<br />
return unless $Transaction->Creator == $RT::SystemUser->id;<br />
<br />
# this is not good idea to skip some transaction types<br />
# even if those are created by system user<br />
return if $SHOW{ $Transaction->Type };<br />
<br />
...<br />
here add your additional conditions<br />
...<br />
<br />
</%INIT><br />
<%ONCE><br />
my %SHOW = map { $_ => 1} qw(<br />
Create Comment Correspond<br />
EmailRecord CommentEmailRecord<br />
);<br />
</%ONCE><br />
<%ARGS><br />
$Transaction => undef<br />
$skip => undef<br />
</%ARGS><br />
</code><br />
<br />
== Additional code snippets ==<br />
<br />
=== Do not hide on History.html page ===<br />
<br />
If you'd like to have an abbreviated history on the main ticket display, but would like the full history in the History tab display, then add the following:<br />
<br />
<nowiki>...<br />
# do nothing if we're on history page<br />
return if $r-&gt;uri =~ /History\.html/;<br />
...<br />
</nowiki><br />
<br />
== RT::Extension::HistoryFilter ==<br />
<br />
I created an extension where you can define which transaction types are shown on the ticket display page. The ticket history page shows always the full history. You can find it at github: [http://github.com/cloos/rt-extension-briefhistory http://github.com/cloos/rt-extension-historyfilter]<br />
<br />
== See also ==<br />
<br />
[[CustomizingWithCallbacks]]</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=HideTransactions&diff=26448HideTransactions2017-01-08T17:19:42Z<p>Barton: /* Reformat Minimal example */</p>
<hr />
<div>= Hiding transactions in tickets' history =<br />
<br />
== Introdduction ==<br />
<br />
You '''should be''' familiar with [[CustomizingWithCallbacks]] as all examples here are based on 'SkipTransaction' callback in Ticket/Elements/ShowHistory Mason component. Create a Callback 'SkipTransaction' in local/html/Callbacks/&lt;MyCallbacks&gt;/Ticket/Elements/ShowHistory/SkipTransaction and pick code below.<br />
<br />
'''For RT 4.2.0 and above '''Ticket/Elements/ShowHistory no longer exists. You will need to hook Elements/ShowHistory's SkipTransaction instead. Keep in mind that this means your transactions may apply to users or queues in addition to tickets and you should tread carefully.<br />
<br />
SkipTransaction callback allows your code to set $$skip variable if you want to skip the current transaction.<br />
<br />
== Minimal example ==<br />
<br />
This is minimal example as starting point that hides all transactions created by the system user.<br />
<br />
<%INIT><br />
$$skip = 1 if $Transaction->Creator == $RT::SystemUser->id;<br />
</%INIT><br />
<%ARGS><br />
$Transaction => undef<br />
$skip => undef<br />
</%ARGS><br />
<br />
== Sane template for your custom code ==<br />
<br />
<nowiki>&lt;%INIT&gt;<br />
# do nothing if transaction is already flagged for skipping<br />
# yes, this is possible, you may have many callbacks that<br />
# skip using different conditions<br />
return if $$skip;<br />
<br />
# do nothing if it's not system user<br />
return unless $Transaction-&gt;Creator == $RT::SystemUser-&gt;id;<br />
<br />
# this is not good idea to skip some transaction types<br />
# even if those are created by system user<br />
return if $SHOW{ $Transaction-&gt;Type };<br />
<br />
...<br />
here add your additional conditions<br />
...<br />
<br />
&lt;/%INIT&gt;<br />
&lt;%ONCE&gt;<br />
my %SHOW = map { $_ =&gt; 1} qw(<br />
Create Comment Correspond<br />
EmailRecord CommentEmailRecord<br />
);<br />
&lt;/%ONCE&gt;<br />
&lt;%ARGS&gt;<br />
$Transaction =&gt; undef<br />
$skip =&gt; undef<br />
&lt;/%ARGS&gt;<br />
</nowiki><br />
<br />
== Additional code snippets ==<br />
<br />
=== Do not hide on History.html page ===<br />
<br />
If you'd like to have an abbreviated history on the main ticket display, but would like the full history in the History tab display, then add the following:<br />
<br />
<nowiki>...<br />
# do nothing if we're on history page<br />
return if $r-&gt;uri =~ /History\.html/;<br />
...<br />
</nowiki><br />
<br />
== RT::Extension::HistoryFilter ==<br />
<br />
I created an extension where you can define which transaction types are shown on the ticket display page. The ticket history page shows always the full history. You can find it at github: [http://github.com/cloos/rt-extension-briefhistory http://github.com/cloos/rt-extension-historyfilter]<br />
<br />
== See also ==<br />
<br />
[[CustomizingWithCallbacks]]</div>Bartonhttps://rt-wiki.bestpractical.com/index.php?title=FindingAnswersAboutRT&diff=26447FindingAnswersAboutRT2017-01-08T17:10:57Z<p>Barton: Reformat sample question framework</p>
<hr />
<div>=== Introduction ===<br />
<br />
Becoming familiar with RT and the resources available to answer your questions can be difficult at first. Frequently you get no answers or very terse answers which don't seem to provide enough guidance. This can be frustrating; it can seem like no one wants to help you when quite often they do.<br />
<br />
=== First, do the legwork ===<br />
<br />
There are a number of places to start your research before you post to the mailing list or send a note to someone who maintains some extension of RT. Here are a few searchable places, listed in order of likely usefulness:<br />
<br />
# [http://wiki.bestpractical.com This Wiki] (the place with lots of answers)<br />
# [[MailingListArchives]] (searchable list archives)<br />
# http://www.google.com/ (I generally start "+RT +MostUniqueErrMsg")<br />
<br />
Search there for answers to your questions. Very frequently you'll find just what you're looking for and perhaps more.<br />
<br />
=== Ask the Right People ===<br />
<br />
If you can't find information on the wiki or in the mailing list archives, you should generally direct your questions to one of the RT [[MailingLists]]. Generally, you'll want to direct your questions to the rt-users mailing list, as that's the right place for them (and nearly everyone on rt-devel is also on rt-users). Posting to rt-users allows you the benefit of experienced RT admins' knowledge, which will likely solve your problem much more quickly than any other approach.<br />
<br />
The rt-devel list is for development issues such as "I'm thinking of implementing thus-and-such and wonder how I should go about it" or "I found a bug and fixed it; here's a patch" and the like.<br />
<br />
While it's often tempting to think you've got a bug or critical issue and should immediately send it to rt-devel, most of the time it's not a bug, but a misconfiguration on your part, which results in a terse note pointing this out and directing you to do the legwork (as mentioned below).<br />
<br />
'''''Please don't create a wiki page to ask a question or add a question to the body of a wiki page.''''' A wiki isn't a support group, it is an information repository. It may be reasonable in some cases to ask a question related to the specific topic of a wiki page in its "Talk" sub-page (particularly if the page content is unclear or incorrect) but as a practical matter that is unlikely to be as productive towards getting a good answer as aking your question on the rt-users mailing list, where there is a broad audience of people following the discussion. The time to create a wiki page is '''''after''''' you have an answer that could be useful to others in the future. <br />
<br />
'''''Please don't send email directly to the bestpractical.com developers'''''. This may seem callous, but consider this: anyone with a bestpractical.com email address is trying to make a living working on RT; the rest of us have a full-time day job and voluntarily contribute to RT as we can. None of us wants to give up precious development time in order to do your initial legwork; conversely, we're happy to help once you've done it and still have questions.<br />
<br />
=== Ask a good question well ===<br />
<br />
Note that there's an extensive treatise on the art of asking good questions well at http://www.catb.org/~esr/faqs/smart-questions.html<br />
<br />
Good questions are clear, concise, and demonstrate that you've done the legwork as mentioned above. They also show an presumption of ignorance on your part unless *you're absolutely certain you really understand exactly what's going on*. I've been working with RT for six years off- and-on and I still learn new things ... usually starting with an incorrect assumption on my part ;]<br />
<br />
A bit of an aside: nothing blows your credibility and diminishes interest in replying quite like an it's-all-screwed-up-and-must-be-a-bug message. RT is a large, complex, mature software system and you're probably not the first person to want to use feature X. It's very likely that there are many people using that feature and they'd be happy to help you join them.<br />
<br />
Also, choose a descriptive subject; it's your first impression and will determine who reads your message. Get the good bits early in the subject (you don't know how many characters I'll see in my mailreader). Here are some good ones (chosen randomly from recent postings):<br />
<br />
Can rt users come from LDAP?<br />
Installing RT on Fedora Core 4<br />
RT VMWare Appliance<br />
Show stalled on AtAGlance list?<br />
<br />
Each of these gives clear guidance to the topic at hand. If it's a subject I might have unique knowledge on or a distinct interest in, I'll definitely make time to read it.<br />
<br />
Here are some horrible ones (chosen randomly from long ago to minimize embarassment):<br />
<br />
RT questions<br />
Lost information<br />
Headings<br />
Great Program!<br />
<br />
As you can see from these last, I have no chance to know what problems lie inside the email or whether I can provide uniquely useful information. On a slow day, I might read one of these to see if I can help. One a busy day, these go straight to the trash.<br />
<br />
Here's a decent framework to hang your question on:<br />
<br />
> '''Subject:''' *FOO* config problems while trying to *BAR*<br />
><br />
> I'm having problems properly configuring *FOO*. I thought I knew<br />
> how it worked, but my attempts have all failed and searching both<br />
> the wiki and the mailing list archives hasn't improved my<br />
> understanding enough to make it work.<br />
><br />
> I'm trying to use FOO to *BAR [insert concise statement of purpose]*<br />
><br />
> So far, I've tried to *[insert concise summary of the saga]*<br />
><br />
> I'm using RT *[version]* on *[OS and version]* with *[all pertinent<br />
> web server details like apache version, mod_perl/fast_cgi, etc.]*<br />
><br />
> Can anyone point me in the right direction?<br />
<br />
<br />
=== Give A Little Bit ===<br />
<br />
If you've come up with the answer to a sticky problem, consider giving back to the community either by summarizing to the mailing list or into the wiki. That'll help the next generation of new RT admins ... and save you answering their questions on the list over and over again. ;]</div>Barton