Can you tell us more about the business scenario, please? Sending e-mails from a report data provider class sounds wrong to me. I would rather use the query from the data contract in the controller class, e.g. in afterOperation(). But what exactly you should do obviously depends on business requirements.
In general, you shouldn't try to do everything at once and mix unrelated code together. I would split your task to three separate steps:
Task 1: Sending an email.
Task 2: Iterating the query, getting e-mail addresses and passing them to Task 1.
Task 3: Executing Task 2 after printing your report.
You can choose the order in which you implement it. For example, if you want to focus on getting the data (and grouping), forget tasks 1 and 3 for a moment. Also, forget about batch processing for now too. Simply create a new class, add a method accepting DTCustTransOpenPerDateContract object and implement (and test) logic to get e-mail addresses. You can show them in infolog for now, because you don't yet have the logic for sending e-mails.
This splitting to several smaller tasks is crucial. It means that you have manageable pieces of work, you can track what is implemented and what's not, you can test individual components before integrating them with other parts and it also leads to a better structure of the solution (than if you mix all things together).
You shouldn't mix all different topics in this forum either. When you split your work to smaller pieces, you'll be able to create threads focusing on individual problems.
Regarding grouping, QueryBuildDataSource class addGroupByField() method for this purpose.