I am new to angulardart and I am working on mailer, but I am having an error that says:
dart_sdk.js:100398
EXCEPTION: Unsupported operation:
Platform._localHostname STACKTRACE: dart:sdk_internal
get localHostname package:mailer2/src/smtp/smtp_options.dart 4:25
new package:mailer2/src/smtp/helper_options.dart 12:24
new
package:DigitalHrSummit/src/components/homepagecomponent/homepage_component.dart
68:21 onSubmit
package:DigitalHrSummit/src/components/homepagecomponent/homepage_component.template.dart
1025:8 [_handle_click_287_0]
package:angular/src/core/linker/app_view.dart 602:29
src__core__linker__app_view_utils.appViewUtils.eventManager.zone.runGuarded.dart.fn
package:angular/src/core/zone/ng_zone.dart 134:16
parent.run.dart.fn dart:sdk_internal
run package:angular/src/core/zone/ng_zone.dart 131:18
[_run] dart:sdk_internal
runGuarded package:angular/src/core/zone/ng_zone.dart 302:22
runGuarded package:angular/src/core/linker/app_view.dart 601:37
event
Basically I just have the sample code that can be found here . I have my gmail username and password in the options variable.
I have the sample code inside my .dart component(homepage_component.dart)
...
import 'package:mailer2/mailer.dart';
...
class HomeComponent(){
void onSubmit(Map<String, dynamic> contactUsInfo) {
//Gmail account used to send email
var options = new GmailSmtpOptions()
..username = 'my-gmail-account'
..password = 'my-gmail-password';
// Create our email transport.
var emailTransport = new SmtpTransport(options);
// Create our mail/envelope.
var envelope = new Envelope()
..from = 'sender-email-here'
..recipients.add('recievers-mail-here')
//..bccRecipients.add('hidden#recipient.com')
..subject = 'Testing the Dart Mailer library'
//..attachments.add(new Attachment(file: new File('path/to/file')))
..text = 'This is a cool email message. Whats up?'
..html = '<h1>Test</h1><p>Hey!</p>';
// Email it.
emailTransport.send(envelope)
.then((envelope) => print('Email sent!'))
.catchError((e) => print('Error occurred: $e'));
}
}
Please help me guys. Thank you.
This library imports dart:io and therefore it isn't usable on the web.
Related
I am writing a program that uses HTTP to get a list of themes from a server, and when transforming the data from JSON I am getting this error.
TypeError: map[$_get] is not a function
packages/outlook/src/provider/response.dart 28:19 fromHTTP
packages/outlook/src/provider/outlook.impl.dart 74:7 <fn>
dart-sdk/lib/async/zone.dart 1653:54 runUnary
dart-sdk/lib/async/future_impl.dart 147:18 handleValue
dart-sdk/lib/async/future_impl.dart 766:44 handleValueCallback
dart-sdk/lib/async/future_impl.dart 795:13 _propagateToListeners
dart-sdk/lib/async/future_impl.dart 566:5 [_completeWithValue]
dart-sdk/lib/async/future_impl.dart 639:7 callback
dart-sdk/lib/async/schedule_microtask.dart 40:11 _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5 _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15 <fn>
here is the method of getting the themes:
Future<OtlResponse<List<OutlookTheme>>> getThemes() {
return http
.post(serverDomain,
body: jsonEncode({'method': RequestMethods.getThemes.name,}))
.then((http.Response resp) {
Map<String, dynamic> body = jsonDecode(resp.body);
OtlResponse<List<OutlookTheme>> response =
OtlResponse<List<OutlookTheme>>.fromHTTP(
map: body,
data: List.from(body['themes'])
.map(( themeMap) => OutlookTheme.fromMap(Map.from(themeMap)))
.toList());
return response;
});
}
After decoding the response I am transforming it into and OtlResponse using this factory as shown here:
factory OtlResponse.fromHTTP({required Map<String, dynamic> map, required T data}) {
return OtlResponse<T>(
success: map['success'] as bool,
data: data,
context: map['context'] as String,
statusCode: map['statusCode'] as int,
methodId: (map['method'] as String).toEnum(RequestMethods.values),
);
}
According to the log , the error is coming from the fromHTTP() factory and where am calling it in the getThemes method. I tried using Map.from() after decoding and its not working. What can I do to fix this? any help would be much appreciated🤝🏿!
Well after stopping main run process and running it, it's now working.
I want to create a seperate log file for each HTTP request made to the application. When ever a request is made to the application, it has to generate a log file in the following format
debug20220713.log
debug20220713_001.log
debug20220713_002.log
Here in each log file there should be only one log available.
Log.Logger = new LoggerConfiguration()
.Enrich.WithExceptionDetails()
.Enrich.FromLogContext()
.WriteTo.Async(y =>
y.Logger(m =>
{
m.WriteTo.File(
new ExpressionTemplate(jsonErrorTemplate),
"error.log", LogEventLevel.Warning,
rollingInterval: RollingInterval.Day);
m.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Warning || e.Level == LogEventLevel.Error);
})
)
.WriteTo.Async(x =>
x.Logger(l =>
{
l.WriteTo.File(new ExpressionTemplate(jsonLogTemplate),
"debug.log", LogEventLevel.Information,
rollingInterval: RollingInterval.Day);
l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Information);
}))
.CreateLogger();
I ended up creating own verision of RollingFileSink which matches my requirement. but internally I still use FileSink class. When I call constructor of FileSink I get this error
"This type and constructor will be removed from the public API in a future version; use WriteTo.File() instead."
I would like to know how can a server side application receive a file (via POST) and then print its contents on the server side.
The most "up to date" related question here was this one: Dart how to upload image
But it is not working anymore (Uncaught Error: type 'String' is not a subtype of type 'HttpBodyFileUpload' of 'fileUploaded').
EDIT:
This is how I send the file (this method is working fine):
import 'dart:html';
import 'dart:async';
HttpRequest request = new HttpRequest();
final _HOST = "127.0.0.1", _PORT = 8123;
Future sendFile(File file) {
var completer = new Completer(); // No need for a Completer. It will be removed.
Uri uri = new Uri(host: _HOST, port: _PORT);
request.open("POST", uri.toString());
var filename = file.name;
final FormData formData = new FormData();
formData.append('file', filename);
request.onLoadEnd.listen((_) {
completer.complete(request.response);
});
request.send(formData);
return completer.future;
}
The server side (I'm stuck here):
void _handlePost(HttpRequest req) {
HttpBodyHandler.processRequest(req).then((body) {
HttpBodyFileUpload fileUploaded = body.body['file'];
print(fileUploaded.content);
});
}
You are appending the filename instead of the Blob (File) to your FormData object. In Dart it looks like there is a special function for appending blobs called appendBlob(name, blob, [filename]).
I'm learning dart and have created a simple contact form - based on the forms tutorial on the dart site, using mailer to send a mail.
So far so good - the client post the message, the server picks up the post data, creates an envelope and sends the mail... but I want to display a comforting message to the person filling out the form, or warn them if it were not sent.
The problem is that the http response is sent before the future that sends the email is completed -
Chris Storm talks about using completers to solve this problem, I think - here: testing error conditions with dart and again in a chapter in Dart for Hipsters, but i am finding it hard to work out how to apply it here.
Here is the complete server code - the comments in the sendMail function show the problem.
import 'dart:io';
import 'dart:convert';
import 'package:mailer/mailer.dart';
final HOST = '127.0.0.1'; // eg: localhost
final PORT = 4040; // a port, must match the client program
void main() {
HttpServer.bind(HOST, PORT).then(gotMessage, onError: printError);
}
void gotMessage(_server) {
_server.listen((HttpRequest request) {
switch (request.method) {
case 'POST':
handlePost(request);
break;
case 'OPTIONS':
handleOptions(request);
break;
default: defaultHandler(request);
}
},
onError: printError); // .listen failed
print('Listening for GET and POST on http://$HOST:$PORT');
}
/**
* Handle POST requests
*
*/
void handlePost(HttpRequest req) {
HttpResponse res = req.response;
print('${req.method}: ${req.uri.path}');
addCorsHeaders(res);
req.listen((List<int> buffer) {
// Create a new string from the characters in the buffer and convert this into a map
Map postData = JSON.decode(new String.fromCharCodes(buffer));
res.write(sendMail(postData));
res.close();
},
onError: printError);
}
/**
* Add Cross-site headers to enable accessing this server from pages
* not served by this server
*
* See: http://www.html5rocks.com/en/tutorials/cors/
* and http://enable-cors.org/server.html
*/
void addCorsHeaders(HttpResponse res) {
res.headers.add('Access-Control-Allow-Origin', '*, ');
res.headers.add('Access-Control-Allow-Methods', 'POST, OPTIONS');
res.headers.add('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
}
void handleOptions(HttpRequest req) {
HttpResponse res = req.response;
addCorsHeaders(res);
print('${req.method}: ${req.uri.path}');
res.statusCode = HttpStatus.NO_CONTENT;
res.close();
}
void defaultHandler(HttpRequest req) {
HttpResponse res = req.response;
addCorsHeaders(res);
res.statusCode = HttpStatus.NOT_FOUND;
res.write('Not found: ${req.method}, ${req.uri.path}');
res.close();
}
void printError(error) => print(error);
sendMail(postData) {
String sentMsg = 'I am waiting for a result to report'; //initialised value
var options = new GmailSmtpOptions()
..username = 'my.mailt#gmail.com' //shove real values in here to test
..password = 'my_password';
var transport = new SmtpTransport(options);
// Create the envelope to send.
var envelope = new Envelope()
..fromName = postData['name']
..from = postData['fromEmail']
..recipients = ['the_recipient#somedomain.com']
..subject = 'Message from contact form'
..text = postData['contactMessage'];
transport.send(envelope)
.then((success) => sentMsg = 'Message sent, thank you.' ) //this will not be returned...
.catchError((e) => sentMsg = 'Message not sent; the reported error was: $e'); // nor will this
return sentMsg; // Sadly the initial value will be returned as the future (transport.send) will not have completed
}
If I get it right, you want to send a response based on the result on transport.send(). If so you can just return it, like
return transport.send(envelope)
.then((success) => sentMsg = 'Message sent, thank you.' )
.catchError((e) => sentMsg = 'Message not sent; the reported error was: $e');
Or using Completer
var c = new Completer();
transport.send(envelope)
.then((success) => sentMsg = 'Message sent, thank you.' )
.then(c.complete)
.catchError((e) => sentMsg = 'Message not sent; the reported error was: $e');
return c.future;
And since you are returning a Future, you have to change how you send your response to client, from
res.write(sendMail(postData));
res.close();
to
sendMail(postData)
.then((result) {
res.write(result);
res.close();
});
Your code doesn't look bad :)
As far as I can see there isn't missing much (haven't tried to execute it though).
request.response.write('Hello, world');
request.response.close();
either in handlePost() (where you have req available or
return the result that you want to return to the client from handlePost() to gotMessage() and add above lines there.
Also take a look at An Introduction to the dart:io Library - Writing web servers
It's frustrating and I'm stuck here for one week and no clue how to fix it ; (
Inspired by Gerwin Sturm's great work (https://github.com/Scarygami/gdg-endpoint-demo) and I like to build the java backend instead.
But unfortunately, every time when I'm trying to call the endpoints API, a NoSuchMethodError error arise.
Exception: NoSuchMethodError : method not found: '_client#0x296594a'
Receiver: Instance of 'Dbentryendpoint'
Arguments: []
Stack Trace: #0 Object.noSuchMethod (dart:core-patch:1737:25)
#1 Dbentryendpoint.listDBEntry (http://127.0.0.1:3030/C:/Users/VincentZhou/dart/dart_dbentryendpoint_v1_api_client/packages/google_dbentryendpoint_v1_api/src/browser/dbentryendpoint.dart:162:16)
#2 main.fetch (http://127.0.0.1:3030/C:/Users/VincentZhou/dart/dart_dbentryendpoint_v1_api_client/demo.dart:24:20)
#3 main (http://127.0.0.1:3030/C:/Users/VincentZhou/dart/dart_dbentryendpoint_v1_api_client/demo.dart:64:8)
Exception: NoSuchMethodError : method not found: '_client#0x296594a'
Receiver: Instance of 'Dbentryendpoint'
Arguments: []
Stack Trace: #0 Object.noSuchMethod (dart:core-patch:1737:25)
#1 Dbentryendpoint.insertDBEntry (http://127.0.0.1:3030/C:/Users/VincentZhou/dart/dart_dbentryendpoint_v1_api_client/packages/google_dbentryendpoint_v1_api/src/browser/dbentryendpoint.dart:124:16)
#2 main.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (http://127.0.0.1:3030/C:/Users/VincentZhou/dart/dart_dbentryendpoint_v1_api_client/demo.dart:56:28)
the source code of demo.dart is almost identical to the original one (https://github.com/Scarygami/gdg-endpoint-demo) and I only change the cloudendpint API and web client ID.
import "dart:html";
import 'packages/google_dbentryendpoint_v1_api/dbentryendpoint_v1_api_browser.dart' as gdglib;
import 'packages/google_plus_v1_api/plus_v1_api_browser.dart' as pluslib;
import 'packages/google_oauth2_client/google_oauth2_browser.dart';
final CLIENT_ID = "878766780041.apps.googleusercontent.com";
final SCOPES = ["https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/plus.me"];
void main() {
var auth = new GoogleOAuth2(CLIENT_ID, SCOPES);
var gdg = new gdglib.Dbentryendpoint(auth);
var plus = new pluslib.Plus(auth);
var container = query("#entries");
var loginButton = query("#login");
var sendButton = query("#send");
InputElement textInput = query("#text");
var authorSpan = query("#author");
pluslib.Person me;
void fetch() {
//gdg.makeAuthRequests = false;
gdg.makeAuthRequests = true;
gdg.listDBEntry(limit:10).then((l) {
container.text = "";
if (l.items != null) {
l.items.forEach((e) {
var p = new ParagraphElement();
var date = e.date.replaceAll("T", " ");
p.text = "$date - ${e.author}: ${e.text}";
container.append(p);
});
}
});
}
loginButton.onClick.listen((Event e) {
auth.login().then((token) {
loginButton.style.display = "none";
plus.makeAuthRequests = true;
plus.people.get("me").then((p) {
me = p;
authorSpan.text = "${me.displayName}:";
authorSpan.style.display = "inline-block";
textInput.style.display = "inline-block";
sendButton.style.display = "inline-block";
sendButton.onClick.listen((Event e) {
var text = textInput.value;
textInput.value = "";
var entry = new gdglib.DBEntry.fromJson({
"author": me.displayName,
"text": text
});
gdg.makeAuthRequests = true;
gdg.insertDBEntry(entry).then((entry) {
fetch();
});
});
});
});
});
on the Google App Engine side, I generate the cloud endpoint class automatically by the GPE and then add the client ID related info:
#Api(name = "dbentryendpoint",
clientIds={Ids.WEB_CLIENT_ID,com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
scopes={"https://www.googleapis.com/auth/userinfo.email"}
)
public class DBEntryEndpoint {
.....
Appreciate for any help!
I think I figure out the way to work around it but I don't know why:
the "generate cloud endpoints" of GPE doesn't generate the path,
for example it generate the method listEntities, not entities.list
the path is necessary to generate resource in
_ah/api/discovery/v1/apis/dbentryendpoint/v1/rest; without path ,there is only schemas and methods, not schemas and resources
without resources, the Dart client generator only export empty
resouces.dart under /commom folder. and the mothods will be inside
entityEndpoints.dart, which cannot correctly recognize the
_client(), which is defined in client.dart under /common.
So the demo.dart cannot find the method.
Question: why the path is ncessary? because GPE dont generate the path automatically, can we have a way to generate the correct dart client file without manually adding the path in google app engine file? Thanks.
The package import does not look correct, try this.
import 'packages:google_dbentryendpoint_v1_api/dbentryendpoint_v1_api_browser.dart' as gdglib;
import 'packages:google_plus_v1_api/plus_v1_api_browser.dart' as pluslib;
import 'packages:google_oauth2_client/google_oauth2_browser.dart';