I am trying to create an mail app in Flutter, right now I am testing the back end then I want to integrate it in my app.
I am using IMAP to get all my emails from my university and insert them into a list using a class called Emails with parameters like subject, date, from, to and body (all string types).
List emails;
Future<EMails> getEmails() async {
ImapFolder inbox = await client.getFolder("inbox");
EMails list;
for (var i = inbox.mailCount; i > 0; i--) {
list.subject = await inbox.fetch(["BODY.PEEK[HEADER.FIELDS (SUBJECT)]"],
messageIds: [i]) as String; //gets the subject
list.date = await inbox.fetch(["BODY.PEEK[HEADER.FIELDS (Date)]"],
messageIds: [i]) as String; //gets the Date
list.from = await inbox.fetch(["BODY.PEEK[HEADER.FIELDS (From)]"],
messageIds: [i]) as String; //gets the From
list.to =
await inbox.fetch(["BODY.PEEK[HEADER.FIELDS (To)]"], messageIds: [i])
as String; //gets the To
list.body = await inbox.fetch(["RFC822.TEXT"], messageIds: [i]) as String;
emails.add(list);
}
return list;
}
The problem is that I can't transform my fetching data into strings.
https://i.imgur.com/vP91ZG1.png
.fetch returns a Future, but it looks like you're not waiting for it yet. Add await in front of each inbox.fetch.
This is documented at https://pub.dev/documentation/imap_client/latest/imap_client/ImapFolder-class.html
.fetch returns a Map>
Map<int, Map<String, dynamic>> subject = await inbox.fetch(["BODY.PEEK[HEADER.FIELDS (SUBJECT)]"],messageIds: [i]);
var mapSubjectEmail = subject[i];
var mapEmail = mapSubjectEmail.values;
var subjectEmail = mapEmail.first as String;
Related
Here I want to do the multiple update commands for the same asset in a single transaction based on conditions.
This is my sample CTO File:
asset SampleAsset identified by id{
o String id
o Integer value
o Integer value2
o Integer value3
}
transaction SampleTransaction {
o Integer value
}
This is my sample JS file:
async function sampleTransaction(tx) {
var value = tx.value;
await updateValue(value);
if(value < MAX){ //MAX=10000
const assetRegistry1 = await getAssetRegistry('org.example.basic.SampleAsset');
var data1 = await assetRegistry.get("1");
data1.value2 = max;
await assetRegistry1.update(data1); //updateNo2
}
else{
const assetRegistry1 = await getAssetRegistry('org.example.basic.SampleAsset');
var data1 = await assetRegistry.get("1");
data1.value3 = value;
await assetRegistry1.update(data1); //UpdateNo2
}
}
async function updateValue(value){
const assetRegistry = await getAssetRegistry('org.example.basic.SampleAsset');
var data = await assetRegistry.get("1");
data.value = value;
await assetRegistry.update(data); //UpdateNo1
}
With the above code, only latest update (UpdateNo2) command is making changes to the asset. what about the first update?
In Hyperledger fabric during proposal simulation any writes made to keys cannot be read back. Hyperledger composer is subject to that same limitation both when it is used with a real fabric implementation as well as when it's used in a simulation mode (for example when using the web connection in composer-playground).
This is the problem you are seeing in your TP function. Every time you perform
let data = await assetRegistry.get("1");
in the same transaction, you are getting the original asset, you don't get a version of the asset that has been updated earlier in the transaction. So what is finally put into the world state when the transaction is committed will be only the last change you made which is why only UpdateNo2 is being seen.
Try something like this (Note I've not tested it)
async function sampleTransaction(tx) {
const assetRegistry = await getAssetRegistry('org.example.basic.SampleAsset');
const data = await assetRegistry1.get("1");
const value = tx.value;
updateValue(data, value);
if(value < MAX){ //MAX=10000
data.value2 = MAX;
}
else{
data.value3 = value;
}
await assetRegistry1.update(data);
}
function updateValue(data, value){
data.value = value;
}
(Note I have left the function structure in just to show the equivalent but updateValue can easily be removed)
I have to send to multipart request to server along with name value pair to server i mean id along with it. Can you please help me how to send id along with multipart files.
Upload() async {
var stream = new https.ByteStream(DelegatingStream.typed(Files[0].openRead()));
var length = await Files[0].length();
var stream1 = new https.ByteStream(DelegatingStream.typed(Files[1].openRead()));
var length1 = await Files[1].length();
var stream2 = new https.ByteStream(DelegatingStream.typed(Files[2].openRead()));
var length2 = await Files[2].length();
var uri = Uri.parse(openurl);
var request = new https.MultipartRequest("POST", uri);
var multipartFile1 = new https.MultipartFile('XX', stream, length,
filename: basename(Files[0].path));
var multipartFile2 = new https.MultipartFile('YY', stream1, length1,
filename: basename(Files[0].path));
var multipartFile3 = new https.MultipartFile('ZZ', stream2, length2,
filename: basename(Files[0].path));
//contentType: new MediaType('image', 'png'));
request.files.add(multipartFile1);
request.files.add(multipartFile2);
request.files.add(multipartFile3);
request.fields.addAll(other)
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}
Thanks in advance
Sathish
I just had a problem similar to this. I had to upload an image along a key-value pair. I realize that I could upload the key-value pair using request.fields:
var request = new http.MultipartRequest("POST", uri);
request.fields['description'] = 'description';
request.fields['File-Name'] = 'FILENAME.jpg';
request.fields['qr_size'] = '3';
I have two classes, a user_api_manager and a base_api_manager. From user_api_manager i call the get method of base_api_manager which performs an http get request and returns a Future<String>. The getrequest is performed but i am not pass the result to my user_api_manager class. The callback result is always null.
This is my user_api_manager.dart
static Future<Map<String,dynamic>> forgotPasswordAPI(String email) async{
String url = Constants.BASE_URL + Constants.FORGOT_PASSWORD_URL + email;
await BaseApiManager.get(url: url).then((val) {
var response = JSON.decode(val);
var status = response['status'];
String message = '';
print(response);
switch (response['status']) {
case Constants.SUCCESS:
message = Constants.SUCCESS_RESPONSE;
break;
case Constants.SERVER_ERROR:
message = Constants.SERVER_ERROR_MESSAGE;
break;
case Constants.UNAUTHORISED:
message = Constants.UNAUTHORISED_MESSAGE;
break;
}
return {'status':status,'message':message};
});
}
and here is my base_api_manager.dart
static Future<String> get({url : String,
parameters : Map ,
headers: Map }) async {
var client = new http.Client();
Map<String,dynamic> resultJSON;
final c = new Completer();
await client.get(url).then((response) { //response is always null
resultJSON = {
'status' : response.statusCode,
'body' : JSON.decode(response.body)
};
c.complete(resultJSON.toString());
return c.future;
});
}
How to solve this issue?
Move the return c.future outside of the response processing, i.e you want to return this from your get otherwise you will return null.
You can simplify the code. That should make it easier to locate the problem
static Future<String> get({url : String, parameters : Map, headers: Map }) async {
var client = new http.Client();
final response = await client.get(url);
print(response.body);
var resultJSON = {
'status' : response.statusCode,
'body' : JSON.decode(response.body)
};
return resultJSON.toString()
}
What does that code print?
const functions = require('firebase-functions');
var IAPVerifier = require('iap_verifier');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.verifyReceipt = functions.database.ref('/Customers/{uid}/updateReceipt')
.onWrite(event => {
const uid = event.params.uid;
var receipt = event.data.val();
(strReceipt).toString('base64');
var client = new IAPVerifier('IAP_secretkey')
client.verifyAutoRenewReceipt(receipt, true,function(valid, msg, data){
console.log(' RECEIPT');
if(valid) {
console.log('VALID RECEIPT');
console.log('msg:' + msg);
var strData = JSON.stringify(data);
console.log('data"' + strData);
const newReceiptRef = admin.database().ref('/Customers/{uid}/');
newReceiptRef.update({'receiptData1': data});
const recVerRef = admin.database().ref('/Customers/{uid}/');
newReceiptRef.update({'updateReceipt': 0});
// update status of payment in your system
}else{
console.log('INVALID RECEIPT');
console.log('msg:' + msg);
var strData = JSON.stringify(data);
console.log('data"' + strData);
}
});
});
This is my node js cloud function. The possible values for 'updateReceipt' are 0 and 1. Is it possible to run the cloud function only when the value is 1?
Thanks.
There is no way to only trigger the function when a specific value is present.
I can think of two options:
Write the nodes to a different branch depending on the updateReceipt value.
Add an if to your code.
The second options is definitely the simplest:
exports.verifyReceipt =
functions.database.ref('/Customers/{uid}/updateReceipt')
.onWrite(event => {
const uid = event.params.uid;
var receipt = event.data.val();
if (receipt.updateReceipt === 0) {
var client = new IAPVerifier('IAP_secretkey')
...
Alternatively, you can keep the updated receipt in a separate branch from the new receipts. That way you can trigger a function separately for just the new receipts.
I'm trying to code sql access to a database using sqljocky in Dart. As I want to make some computation with the result returned by my database Handler, the method return a Future.
But when I try to run it, I'm getting the following error:
Uncaught Error: The null object does not have a method 'then'`
I've ran the debugger and found that this error raise on:
db.query('select * from user where email="$email"').then(...)
but the catchError clause doesn't fire.
My handler method is:
// db is a ConnectionPool
Future<Map<String,String>> queryUser(String email){
print(email);
db.query('select * from user where email="${email}"').then((result) { // here raise the error
Map<String,String> results = new Map<String,String>();
result.forEach((row){
results['status'] = '200';
results['ID'] = row[0];
results['Image'] = row[1];
results['Name'] = row[2];
results['Email'] = row[3];
results['Password'] = row[4];
});
return results;
}).catchError((error){
Map<String,String> results = new Map<String,String>();
results['status'] = '500';
return results;
});
}
And the method that call this handler is:
List getUser(String email) {
Future<Map<String,String>> result = dbhandler.queryUser(email);
result.then((Map<String,String> result) {
String statuscode = result['status'];
result.remove('status');
String json = JSON.encode(result);
List pair = new List();
pair.add(statuscode);
pair.add(json);
return pair;
});
If I run the query directly in phpmyadmin, it return correct data, so it is correct.
Can someone give me a hint about how to solve it?
The queryUser() method will always return null, as there is no return statement. In the next release of Dart there will be a static hint warning for this, but at the moment there is none.
Perhaps the code below is what you meant to do. Note the initial return statement before db.query(), and the extra result.toList() call. I haven't tested this, so there's probably a typo or two.
Future<Map<String,String>> queryUser(String email){
print(email);
return db.query('select * from user where email="${email}"')
.then((result) => result.toList())
.then((rows) {
var row = rows.single;
Map<String,String> results = new Map<String,String>();
results['status'] = '200';
results['ID'] = row[0];
results['Image'] = row[1];
results['Name'] = row[2];
results['Email'] = row[3];
results['Password'] = row[4];
return results;
}).catchError((error){
Map<String,String> results = new Map<String,String>();
results['status'] = '500';
return results;
});
}
You can also make this a bit cuter using map literals:
Future<Map<String,String>> queryUser(String email){
return db.query('select * from user where email="${email}"')
.then((result) => result.toList())
.then((rows) => <String, String> {
'status': '200',
'ID': rows.single[0],
'Image': rows.single[1],
'Name': rows.single[2],
'Email': rows.single[3],
'Password': rows.single[4] })
.catchError((error) => <String, String> {'status': '500'});
}
Finally I found the answer using Completer to control the Future object, but the real problem was, as Greg Lowe said, that my methods doesn't return anything as they come to end before the then clause.
Using completer, I've made my query method as:
Future<Map<String,String>> queryUser(String email){
Completer c = new Completer();
db.query('select * from user where email="$email"').then((result) {
Map<String,String> results = new Map<String,String>();
result.forEach((row){
results['status'] = '200';
results['ID'] = row[0].toString();
results['Image'] = row[1];
results['Name'] = row[2];
results['Email'] = row[3];
results['Password'] = row[4];
}).then((onValue){
c.complete(results);
});
}).catchError((error){
Map<String,String> results = new Map<String,String>();
results['status'] = '500';
c.completeError((e) => print("error en queryUser"));
});
return c.future;
}
I also solved an error when using the foreach method, at first I supposed it return nothing, but after that, I noticed that it return a Future, so I added a then clause.
And my getUser method:
Future<List> getUser(String email) {
Completer c = new Completer();
Future<Map<String,String>> result = dbhandler.queryUser(email);
result.then((Map<String,String> result) {
String statuscode = result['status'];
result.remove('status');
String json = JSON.encode(result);
List pair = new List();
pair.add(statuscode);
pair.add(json);
c.complete(pair);
});
return c.future;
}
After those changes, everything works right