an artist s illustration of artificial intelligence ai this image was inspired neural networks used in deep learning it was created by novoto studio as part of the visualising ai proje

How to Automatically Send Email of Daily Circulation Reports from Koha

Share this post on:

Managing a library’s daily circulation statistics often involves performing the same routine every morning: log in to Koha, run a circulation report, export the results, download the CSV file, and then review the previous day’s activity.

For a busy library, this quickly becomes a repetitive task.

In my case, I wanted Koha to handle this automatically. The objective was simple:

  • Run a report automatically every night.
  • Generate a CSV containing all books currently issued as of midnight.
  • Generate another CSV containing the circulation transactions that took place during the day, including issues, reissues and returns.
  • Send both reports automatically to my email.
  • Require no manual intervention.

This article explains how I implemented this automation on Koha 24.11.04.000 running on Ubuntu Linux.

The same approach can be adapted to other recent Koha versions and Debian/Ubuntu installations.

What We Are Going to Build

The final workflow looks like this:

                    Koha
                     │
                     │
              Saved SQL Reports
                     │
                     ▼
             runreport.pl
                     │
                     ▼
              Linux Cron Job
                     │
              Scheduled at 00:00
                     │
                     ▼
             Generate CSV files
                     │
                     ▼
              Koha SMTP / Mail
                     │
                     ▼
                 Email Inbox

At midnight, the server automatically executes the saved Koha reports and sends the resulting CSV files to the configured email address.

The next morning, the reports are already waiting in the inbox.

Why Automate Daily Circulation Reports?

Koha already provides an excellent reporting system. However, running the same report manually every day is unnecessary when the server can do it automatically.

For example, a librarian may want to know:

  1. How many books are currently issued?
  2. Which books are currently out of the library?
  3. How many circulation transactions occurred during the day?
  4. How many books were issued?
  5. How many books were reissued or renewed?
  6. How many books were returned?

These reports are particularly useful for daily monitoring and maintaining circulation statistics.

Instead of manually generating them every morning, we can let Linux execute them on a schedule.

Requirements

Before starting, make sure you have:

  • Koha installed on an Ubuntu/Debian server
  • Access to the Koha staff interface
  • Permission to create Koha SQL reports
  • SSH or terminal access to the Koha server
  • Koha’s email/SMTP functionality configured and working
  • Linux Cron enabled
  • A valid email address where the reports should be delivered

My environment was:

Operating System: Ubuntu Server Linux
Koha: 24.11.04.000
Report format: CSV
Email: Gmail SMTP configured on the Postfix server
Scheduler: Linux Cron

Step 1: Create the Required Reports in Koha

The first step is to create the reports that we want to automate.

The important point here is that we do not need to create a new reporting mechanism.

Koha already has a Reports module and provides the runreport.pl command-line utility for executing saved reports.

We can therefore:

  1. Create and test the report in Koha.
  2. Save it.
  3. Identify its Report ID.
  4. Execute that saved report from the Linux command line.
  5. Schedule its execution with Cron.

This is much cleaner than creating a separate PHP or Python reporting application.

Report 1: Books Currently Issued

My first report provides the list of books that are currently issued.

The report essentially answers:

“How many books are out of the library at this moment?”

The exact SQL will depend on your library’s requirements and the fields you want to include.

For example, a basic report can retrieve information about currently issued items using Koha’s circulation tables.

A report might include fields such as:

Card Number
Borrower Name
Barcode
Title
Author
Call Number
Issue Date
Due Date
Library

The important part is that the report should return only currently active issues.

After creating the report, save it in Koha.

For example:

Report Name:
Total Books Currently Issued

Koha assigns the saved report an ID.

For my setup, the report ID was:

17

Your Report ID will almost certainly be different.

Report 2: Daily Circulation Transactions

The second report is slightly different.

Instead of showing the current status of loans, I wanted a historical list of transactions that occurred during the day.

This includes transactions such as:

  • Issues
  • Reissues/Renewals
  • Returns

This report allows me to see what actually happened in the library during the previous day.

For example:

Date       Card No.   Member Name   Barcode   Title          Transaction
2026-09-25 ABC001     John Doe      10001     Book Title     Issue
2026-09-25 ABC002     Jane Doe      10002     Another Book   Return
2026-09-25 ABC003     Student A     10003     Library Book   Renewal

Again, the exact SQL depends on the circulation information you want to capture.

Save this as another Koha report.

For example:

Report Name:
Daily Circulation Transactions

Make a note of its Report ID.

Step 3: Find the Koha runreport.pl Script

Koha provides a command-line script called:

runreport.pl

On my installation, the script was located at:

/usr/share/koha/bin/cronjobs/runreport.pl

You can find it on your server with:

sudo find /usr/share/koha -name runreport.pl 2>/dev/null

You may get:

/usr/share/koha/bin/cronjobs/runreport.pl

The exact location may vary depending on how Koha was installed.

Step 4: Important: Run the Script Through koha-shell

This was an important part of the setup.

Initially, I tried executing the script directly with Perl:

sudo perl /usr/share/koha/bin/cronjobs/runreport.pl ...

Koha returned:

Can't locate Koha/Script.pm in @INC

The problem was not the report itself.

The Koha Perl environment had not been initialized.

Koha’s Perl modules were therefore not available in the normal system Perl environment.

The solution is to execute the command inside the Koha instance’s shell environment.

First, identify your Koha instance:

sudo koha-list

For example:

library

Then enter the Koha shell:

sudo koha-shell library

Replace library with your actual Koha instance name.

Once inside the Koha shell, execute:

perl /usr/share/koha/bin/cronjobs/runreport.pl --help

If the command displays the available options, the Koha environment is working correctly.

This step is particularly important on package-based Debian/Ubuntu Koha installations.

Step 5: Test the Report Manually

Before configuring Cron, always test the command manually.

Do not jump directly to Cron.

That makes troubleshooting unnecessarily painful because then you have three suspects: Koha, Cron and email delivery. Humans apparently enjoy debugging three systems at once.

Start the Koha shell:

sudo koha-shell library

Then execute your report.

A typical command looks like:

perl /usr/share/koha/bin/cronjobs/runreport.pl \
    --format=csv \
    --csv-header \
    17

Here:

--format=csv

requests CSV output.

--csv-header

adds column headings to the CSV.

17

is the saved Koha Report ID.

Replace 17 with your actual report ID.

Step 6: Test Email Delivery

Once the report itself works, test sending it by email.

The command I used was:

perl /usr/share/koha/bin/cronjobs/runreport.pl \
    --format=csv \
    --csv-header \
    --email \
    --attachment \
    --to="me@rupindersingh.in" \
    --from="circulation@librarymail.com" \
    --subject="Daily Koha Circulation Report" \
    17

Replace the following values:

me@rupindersingh.in

with the email address that should receive the report.

And:

circulation@librarymail.com

with your configured sender address.

The Report ID:

17

must also be replaced with your own report ID.


Understanding the Command

Let’s break it down.

--format=csv

--format=csv

tells Koha to generate the report as CSV.

CSV is particularly useful because it can be opened directly in Microsoft Excel, LibreOffice Calc, Google Sheets and other spreadsheet applications.


--csv-header

--csv-header

adds the report’s column headings to the CSV file.

Without headers, the report would contain data but the meaning of each column would be less obvious.


--email

--email

tells runreport.pl to send the report by email.


--attachment

--attachment

causes the report output to be sent as an attachment.

This is useful when the report contains many records.

Instead of putting thousands of rows into the body of an email, the recipient receives a CSV file.


--to

--to="me@rupindersingh.in"

specifies the recipient.


--from

--from="circulation@librarymail.com"

specifies the sender.

This should normally correspond to an email address configured for your library/Koha installation.


--subject

--subject="Daily Koha Circulation Report"

sets the email subject.


17

Finally:

17

is the Koha saved report ID.

Step 7: Verify the Email

After executing the command, check your inbox.

You should receive an email with a CSV attachment.

For example:

Subject:
Daily Koha Circulation Report

with an attachment similar to:

report.csv

Open the attachment and verify that the contents match the report you generated from the Koha staff interface.

Do this before moving to Cron.

Step 8: Automate the Report with Linux Cron

Once the command works manually, we can automate it.

Linux provides a scheduler called Cron.

Cron can execute commands automatically at specified times.

For example:

00:00 every day

can be represented as:

0 0 * * *

Step 9: Create a Shell Script

Although it is possible to put the entire Koha command directly into Cron, I recommend creating a small shell script.

This makes the setup easier to maintain and troubleshoot.

Create a directory:

sudo mkdir -p /opt/koha-automation

Create the script:

sudo nano /opt/koha-automation/daily-circulation-report.sh

Add:

#!/bin/bash

REPORT_ID="17"

TO_EMAIL="me@rupindersingh.in"
FROM_EMAIL="circulation@librarymail.com"

RUNREPORT="/usr/share/koha/bin/cronjobs/runreport.pl"

LOG_FILE="/var/log/koha-daily-circulation.log"

echo "$(date '+%Y-%m-%d %H:%M:%S') - Starting Koha report" >> "$LOG_FILE"

perl "$RUNREPORT" \
    --format=csv \
    --csv-header \
    --email \
    --attachment \
    --to="$TO_EMAIL" \
    --from="$FROM_EMAIL" \
    --subject="Daily Koha Circulation Report" \
    "$REPORT_ID" \
    >> "$LOG_FILE" 2>&1

STATUS=$?

echo "$(date '+%Y-%m-%d %H:%M:%S') - Report finished with exit code $STATUS" >> "$LOG_FILE"

Save the file.

Make it executable:

sudo chmod +x /opt/koha-automation/daily-circulation-report.sh

Step 10: Test the Shell Script

Run:

sudo koha-shell library

However, there is an important consideration here.

Because koha-shell initializes the Koha environment, your Cron execution also needs to run within that environment.

One reliable approach is to have the Cron job invoke the script through koha-shell.

For example, if your instance name is:

library

you can run:

sudo koha-shell library -- /opt/koha-automation/daily-circulation-report.sh

Depending on the exact koha-shell behavior in your Koha packaging, you may instead use the shell wrapper/environment mechanism provided by your installation.

The key principle is:

The Cron process must execute runreport.pl with the Koha Perl environment initialized.

This is why simply copying the successful interactive command into a root Cron job can sometimes result in the same Koha/Script.pm error returning.

Step 11: Configure Cron

Edit the root user’s Cron table:

sudo crontab -e

For execution at midnight every day:

0 0 * * * sudo koha-shell library -- /opt/koha-automation/daily-circulation-report.sh

Replace:

library

with your actual Koha instance name.

If the Cron entry itself is already running as root, sudo inside the Cron command may not be necessary.

For example:

0 0 * * * koha-shell library -- /opt/koha-automation/daily-circulation-report.sh

The exact invocation should match the koha-shell syntax supported by your installed Koha package.

Step 12: Verify the Cron Job

Check the root Cron table:

sudo crontab -l

You should see your scheduled job.

For example:

0 0 * * * koha-shell library -- /opt/koha-automation/daily-circulation-report.sh

Step 13: Verify the Server Time

Cron uses the server’s system time.

Check it with:

timedatectl

For an Indian server, I recommend ensuring that the timezone is:

Asia/Kolkata

If necessary:

sudo timedatectl set-timezone Asia/Kolkata

Then verify:

date

This prevents a surprisingly common problem where someone schedules something for midnight and the server cheerfully interprets midnight as UTC.

Automating Multiple Reports

In my setup, I wanted two different reports.

Report 1

Current circulation status

This provides the list of all books currently issued as of midnight.

Report 2

Daily circulation transactions

This provides the transactions that occurred during the day, including:

  • Issues
  • Reissues/Renewals
  • Returns

Both reports are sent automatically by email.

The important thing is that they are separate saved Koha reports.

This makes the reporting system much easier to maintain because each report has a single purpose.

Running Two Reports Automatically

You can execute multiple reports from the same automation script.

For example:

REPORT_CURRENT="17"
REPORT_DAILY="18"

Then execute the reports separately.

For example:

perl "$RUNREPORT" \
    --format=csv \
    --csv-header \
    --email \
    --attachment \
    --to="$TO_EMAIL" \
    --from="$FROM_EMAIL" \
    --subject="Current Books Issued" \
    "$REPORT_CURRENT"

and:

perl "$RUNREPORT" \
    --format=csv \
    --csv-header \
    --email \
    --attachment \
    --to="$TO_EMAIL" \
    --from="$FROM_EMAIL" \
    --subject="Daily Circulation Transactions" \
    "$REPORT_DAILY"

This gives you two separate emails and two separate CSV attachments.

Alternatively, your Koha version and configuration may allow multiple reports to be handled through a single invocation. I prefer keeping separate reports and clearly named email subjects because it makes troubleshooting and archiving easier.

A Better Naming Convention

If you receive reports every day, meaningful email subjects become very useful.

For example:

Koha - Current Books Issued - 25 Sep 2026

and:

Koha - Daily Circulation - 25 Sep 2026

You can generate the date dynamically in your shell script.

For example:

REPORT_DATE=$(date '+%d-%b-%Y')

Then:

--subject="Koha - Daily Circulation - $REPORT_DATE"

The resulting email will contain:

Koha - Daily Circulation - 25-Sep-2026

This makes searching your mailbox considerably easier.

Logging

It is a good idea to maintain a log file.

For example:

/var/log/koha-daily-circulation.log

You can check it using:

sudo tail -50 /var/log/koha-daily-circulation.log

For live monitoring:

sudo tail -f /var/log/koha-daily-circulation.log

You can also check whether Cron actually executed the command.

On Ubuntu:

sudo grep CRON /var/log/syslog | tail -20

If you use Postfix for email delivery, check:

sudo tail -f /var/log/mail.log

This is particularly useful when the report appears to have run but the email does not arrive.

Troubleshooting

1. Can't locate Koha/Script.pm

If you see:

Can't locate Koha/Script.pm in @INC

do not immediately reinstall Koha.

The first thing to check is whether you are running the report inside the Koha environment.

Use:

sudo koha-shell YOUR_INSTANCE

Then execute:

perl /usr/share/koha/bin/cronjobs/runreport.pl ...

In my case, this solved the problem.

2. The Report Runs but No Email Arrives

First check the mail system.

If using Postfix:

sudo tail -f /var/log/mail.log

Also verify that the sender address is valid:

circulation@librarymail.com

and that your SMTP configuration is functioning correctly.

You can also test Koha’s normal email notifications to make sure the problem isn’t specific to runreport.pl.

3. Cron Runs but the Report Does Not

Check:

sudo grep CRON /var/log/syslog | tail -30

Then check your custom report log:

sudo tail -50 /var/log/koha-daily-circulation.log

Cron has a very particular talent for doing exactly what you told it to do rather than what you meant.

4. The Report Works Manually but Not from Cron

This is usually an environment problem.

Your interactive shell may have Koha’s environment configured, while Cron has a much smaller environment.

That is why the report should be tested in the same environment in which Cron will execute it.

In particular, verify:

which perl

and:

sudo koha-shell YOUR_INSTANCE

Then test the report from there.

Security Considerations

The shell script contains an email address, but it should not normally contain your SMTP password if the server is already configured to handle SMTP through Postfix or Koha.

Make sure the script is not writable by ordinary users.

For example:

sudo chown root:root /opt/koha-automation/daily-circulation-report.sh
sudo chmod 750 /opt/koha-automation/daily-circulation-report.sh

Also avoid putting passwords directly into Cron entries.

Why This Approach Is Useful for Libraries

This is more than simply automating one report.

The same principle can be used for many routine library-management tasks.

For example, you can automate:

  • Daily circulation reports
  • Overdue item reports
  • Items with high overdue fines
  • Newly cataloged books
  • Membership statistics
  • Daily accession reports
  • Items returned during the previous day
  • Lost item reports
  • Department-wise circulation
  • Branch-wise circulation
  • Collection statistics
  • Pending holds/reservations
  • Acquisition reports

Once a report exists in Koha and can be executed from the command line, Linux Cron can turn it into a scheduled operational report.

My Final Workflow

My automated setup now works like this:

                12:00 AM
                    │
                    ▼
             Linux Cron starts
                    │
                    ▼
             Koha environment
                    │
                    ▼
          ┌─────────┴─────────┐
          │                   │
          ▼                   ▼
   Current Issues      Daily Transactions
          │                   │
          ▼                   ▼
       CSV file            CSV file
          │                   │
          └─────────┬─────────┘
                    │
                    ▼
                 SMTP
                    │
                    ▼
              Email Inbox
                    │
                    ▼
              Next Morning

I no longer need to manually log in to Koha every morning just to run the same reports.

The server generates the reports automatically during the night, and the CSV files are waiting in my inbox when I start work.

Conclusion

Koha already provides a powerful reporting system, but combining it with Linux’s scheduling capabilities makes it considerably more useful for day-to-day library administration.

The important components are:

Koha Saved Reports
        +
runreport.pl
        +
koha-shell
        +
Linux Cron
        +
SMTP

Together, these provide a simple and reliable reporting pipeline.

The biggest lesson from the setup is that runreport.pl should be executed within the Koha environment. Running it directly with the system Perl interpreter can produce errors such as:

Can't locate Koha/Script.pm in @INC

Using koha-shell ensures that Koha’s Perl environment and modules are available.

For libraries already using Koha on Ubuntu or Debian, this is a relatively small automation that can eliminate a repetitive daily task and provide a consistent record of circulation activity.

And, as usual, the computer is perfectly happy to do the boring work at midnight while the librarian gets to do something more useful the next morning.

Author: Rupinder Singh

I am a tireless intelligence seeker, coincidentally I am a computer guy too, who is passionate about Information Tools and Open-Source software. I Read Books, play Computer Games, Climb Mountains, when I am not changing the code.

View all posts by Rupinder Singh >

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.